<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/codeblog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/codeblog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/codeblog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/codeblog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/codeblog/css/main.css">


<link rel="stylesheet" href="/codeblog/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/codeblog/lib/pace/pace-theme-minimal.min.css">
  <script src="/codeblog/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"skycoin.gitee.io","root":"/codeblog/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null,"activeClass":"valine"},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="立志完成前端知识体系的架构">
<meta property="og:type" content="website">
<meta property="og:title" content="若水的前端博客">
<meta property="og:url" content="http://skycoin.gitee.io/codeblog/index.html">
<meta property="og:site_name" content="若水的前端博客">
<meta property="og:description" content="立志完成前端知识体系的架构">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="若说">
<meta property="article:tag" content="前端 、 技术">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://skycoin.gitee.io/codeblog/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>若水的前端博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/codeblog/atom.xml" title="若水的前端博客" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>
    <a target="_blank" rel="noopener" href="https://your-url" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#70B7FD; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/codeblog/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">若水的前端博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">最优秀的模式往往是最简单的东西</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/codeblog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/codeblog/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/codeblog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/codeblog/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://skycoin.gitee.io/codeblog/2021/02/27/%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4083356047,3551369852&fm=26&gp=0.jpg">
      <meta itemprop="name" content="若说">
      <meta itemprop="description" content="立志完成前端知识体系的架构">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="若水的前端博客">
    </span>
      <header class="post-header">
      
        <i class="fa fa-thumb-tack"></i>
        <font color=7D26CD>置顶</font>
      
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/codeblog/2021/02/27/%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/" class="post-title-link" itemprop="url">Javascript基础（一）：在html中引入script</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-27 10:14:52" itemprop="dateCreated datePublished" datetime="2021-02-27T10:14:52+08:00">2021-02-27</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-15 09:24:14" itemprop="dateModified" datetime="2021-04-15T09:24:14+08:00">2021-04-15</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/codeblog/categories/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">前端框架</span></a>
                </span>
            </span>

          
            <span id="/codeblog/2021/02/27/%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/" class="post-meta-item leancloud_visitors" data-flag-title="Javascript基础（一）：在html中引入script" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/codeblog/2021/02/27/%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/codeblog/2021/02/27/%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="1-script-元素"><a href="#1-script-元素" class="headerlink" title="1.script 元素"></a>1.script 元素</h2><p>1.1 主要的作用：将 js 代码插入到 HTML 中。</p>
<p>1.2 script 标签中的属性</p>
<ul>
<li><p>async : 可选.表示应该立即开始下载脚本，但不能阻止其他页面动作</p>
</li>
<li><p>charset : 可选，使用 src 属性指定的代码字符集</p>
</li>
<li><p>crossorigin : 可选。配置相关请求的 cors（跨资源共享）设置。默认不使用。<code>crossorigin=&quot;anonymous&quot;</code>配置文件请求不必设置凭据标志，<code>crossorigin=&quot;use-credentials&quot;</code>设置凭据标志，意味着出战请求会包含凭据</p>
</li>
<li><p>defer ：可选。表示脚本可以延迟到文档完全被解析和显示之后再执行</p>
</li>
<li><p>integrity ：允许比对接收到的资源和指定的加密签名以验证资源完整性</p>
</li>
<li><p>src ：可选，表示包含要执行的代码的外部文件</p>
</li>
<li><p>type ：可选，代替 language，表示代码块中脚本语言的内容类型，如果这个值是 module，则代码块会被当成 es6 模块，而且只有这个时候代码中才能出现 import 和 export 关键字</p>
<p>1.3 使用 script 的方式有两种：</p>
<p>1.通过它直接在网页中嵌入 js 代码。</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">sayHi</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  	<span class="built_in">console</span>.log(<span class="string">&quot;Hi!&quot;</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>包含在 script 内的代码会从上到下解释。被解释的是一个函数定义，并且该函数会保存在解释器环境中。在 script 元素中的代码被计算完成之前，页面的其余内容不会被加载，也不会被显示。</p>
<p>注意 ：在使用行内 js 代码时，要注意代码中不能出现字符串<code>script</code> 。浏览器在解析行内脚本的方式决定了它在看到字符串<code>&lt;/script&gt;</code>时，会将其当成结束的<code>&lt;/script&gt;</code>标签。想避免这个问题，只需要<code>\</code>即可</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;<span class="function"><span class="keyword">function</span> <span class="title">sayScript</span>(<span class="params"></span>)</span>&#123;<span class="built_in">console</span>.log(<span class="string">&quot;&lt;/script&gt;&quot;</span>)&#125;&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>2.引入外部文件的 js</p>
<p>必须使用 src</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=<span class="string">&quot;example.js&quot;</span> /&gt;</span><br></pre></td></tr></table></figure>

<p>文件本身只需包含要放在<code>&lt;script&gt;</code>的起始及结束标签中间的 js 代码。与解释行内 js 一样，在解释外部 js 文件时，页面也会阻塞。（阻塞时间也包含下载文件的时间）</p>
<p>使用了 src 属性的<code>&lt;script&gt;</code>元素不应该再在<code>&lt;script&gt;</code>标签中包含其他 js 代码，如果两者都提供的话，则浏览器只会下载并执行脚本文件，从而忽略行内代码</p>
<p><code>&lt;script&gt;</code>最为强大、同时也备受争议的地方在于，他可以包含来自外部域的 js 文件。跟<code>&lt;img&gt;</code>很像。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=<span class="string">&quot;http://www.baidu.com/api.js&quot;</span> /&gt;</span><br></pre></td></tr></table></figure>

<p>浏览器在解析这个资源时，会向 src 属性指定的路径发送一个 GET 请求，以取得相应资源。但要注意，要引用自己的域，防止引用其他域的恶意攻击。</p>
<p>不管包含的什么代码，浏览器都会按照<code>script</code>出现的顺序依次解释它们，前提是没有使用 defer 和 async 属性和。之后的 script 标签，必须得等待前一个执行之后，才可以继续执行</p>
<p>1.4 标签的位置</p>
<p>过去所有的<code>&lt;script&gt;</code>元素都放在页面的 head 标签内，这样做法的目的就是把外部的 css 和 js 文件都集中放在一起。这样就意味着只有将所有的 js 代码都下载，解析和解释完成之后，才能开始渲染页面。对于需要很多 js 的页面，这个会导致页面渲染的明显延迟。在此期间浏览器窗口完全空白。</p>
<p>现代 web 应用程序通常将所有的 js 引用放在 body 元素中的页面内容后面，解决页面加载空窗期的问题，</p>
<p>1.5 推迟执行脚本</p>
<p>defer：这个属性表示脚本在执行的时候不会改变页面的结构，也就是，脚本会被延迟到整个页面都解析完毕后在运行。设置上这个属性之后，就相当于告诉浏览器立即下载，但延迟执行。考虑到这点，还是要把推迟执行的脚本放在页面底部比较好。</p>
<p>注意：defer 属性只对外部脚本文件才有效。</p>
<p>1.6 异步执行脚本</p>
<p>在改变脚本处理方式上看，async 属性与 defer 类似。它们两者都是只适合用于外部脚本，都会告诉浏览器立即开始下载。与 defer 不同的是，标记为 async 的脚本并不保证能按照它们出现的次序执行</p>
<p>1.7 动态加载脚本</p>
<p>除了 script 标签外，还有其他方式可以加载脚本。因为 js 可以使用 DOM API,所以通向 DOM 中动态添加 script 元素同样可以加载指定的脚本。只要创建一个 sript 元素并添加到 DOM 即可</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> script = <span class="built_in">document</span>.createElement(<span class="string">&quot;script&quot;</span>);</span><br><span class="line">script.src = <span class="string">&quot;a.js&quot;</span>;</span><br><span class="line">script.async = <span class="literal">false</span>; <span class="comment">//默认情况是异步，所以为了统一动态脚本的加载行为，可以设置成同步</span></span><br><span class="line"><span class="built_in">document</span>.head.appendChild(script);</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <div>
          
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://skycoin.gitee.io/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4083356047,3551369852&fm=26&gp=0.jpg">
      <meta itemprop="name" content="若说">
      <meta itemprop="description" content="立志完成前端知识体系的架构">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="若水的前端博客">
    </span>
      <header class="post-header">
      
        <i class="fa fa-thumb-tack"></i>
        <font color=7D26CD>置顶</font>
      
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/" class="post-title-link" itemprop="url">Javascript基础（二）：javascript基本概念</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-27 10:14:52" itemprop="dateCreated datePublished" datetime="2021-02-27T10:14:52+08:00">2021-02-27</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-15 09:24:09" itemprop="dateModified" datetime="2021-04-15T09:24:09+08:00">2021-04-15</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/codeblog/categories/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">前端框架</span></a>
                </span>
            </span>

          
            <span id="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/" class="post-meta-item leancloud_visitors" data-flag-title="Javascript基础（二）：javascript基本概念" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>[toc]</p>
<h2 id="1-语法"><a href="#1-语法" class="headerlink" title="1.语法"></a>1.语法</h2><p>1.1 区分大小写</p>
<p>​ ECMAScript 中的一切（变量、函数名和操作符）都区分大小写</p>
<p>1.2 标识符</p>
<p>​ 指的就是变量、函数、属性的名字。或者函数的参数。标识符可以是按照下列格式规则组合起来的一或多个字符</p>
<ul>
<li><p>第一个字符必须是一个字母、下划线或一个美元符 fv 号</p>
</li>
<li><p>其他字符可以是字母、下划线、美元符号或数字</p>
</li>
<li><p>标识符中字母也可以包含扩展的 ASCII 或 Unicode 字母字符</p>
</li>
<li><p>惯例，ECAMAScript 标识符采用驼峰大小写格式，也就是第一个字母小写，剩下的每个单词的首字母大写</p>
</li>
<li><p>不能把关键字、保留字、true、false 或 null 用作标识符</p>
<p>1.3 注释</p>
</li>
<li><p>单行注释 //</p>
</li>
<li><p>多行注释 /* */</p>
<p>1.4 严格模式</p>
</li>
</ul>
<p>为 js 定义了一种不同的解析与执行模型。在严格模式下，ECMAScript 中一些不确定的行为将得到处理，而且对某些不安全的操作也会抛出错误。因此要在整个脚本中启用严格模式。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&quot;use strict&quot;</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>它是一个编译指示，用于告诉支持 js 引擎切换到严格模式</p>
<p>1.5 语句</p>
<p>​ ECMAScript 中的语句以一个分号结尾；如果省略分号，则由解析器确定语句的结尾</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> sum = a + b;</span><br><span class="line"><span class="keyword">var</span> diff = a - b;</span><br></pre></td></tr></table></figure>

<p>虽然语句结尾的分号不是必须的，但是建议还是不要省略，因为加上这个分号可以避免很多的错误</p>
<p>虽然条件控制语句只在执行多条语句的情况下才要求使用代码块，但最佳实践是-即使代码块中只有一条语句，也要使用代码块</p>
<p>1.6 关键字和保留字</p>
<p>ECMA-262 描述了一组具有特定用途的关键字，这些关键字可用于表示控制语句的开始或结束，或者用于执行特定操作。关键字是语言保留的，不能用作标识符，下面是 ECMAScript 全部的关键字</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">break</span> <span class="keyword">do</span> <span class="keyword">instanceof</span> <span class="keyword">typeof</span> <span class="keyword">case</span> <span class="keyword">else</span> <span class="keyword">new</span> <span class="keyword">var</span> <span class="keyword">catch</span> <span class="keyword">finally</span> <span class="keyword">return</span> <span class="keyword">void</span> <span class="keyword">continue</span> <span class="keyword">for</span> <span class="keyword">switch</span> <span class="keyword">while</span> <span class="keyword">debugger</span>* <span class="function"><span class="keyword">function</span> <span class="title">this</span> <span class="title">with</span> <span class="title">default</span> <span class="title">if</span> <span class="title">throw</span> <span class="title">delete</span> <span class="title">in</span> <span class="title">try</span></span></span><br></pre></td></tr></table></figure>

<p>第 5 版在非严格模式下运行时的保留字缩减为</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">enum</span> <span class="keyword">extends</span> <span class="title">super</span> <span class="title">const</span> <span class="title">export</span> <span class="title">import</span></span></span><br></pre></td></tr></table></figure>

<p>在严格模式下施加了限制</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">implements package public interface private <span class="keyword">static</span> <span class="keyword">let</span> protected <span class="keyword">yield</span></span><br></pre></td></tr></table></figure>

<p>1.7 变量</p>
<p>ECMAScript 的变量是松散类型的，也就是可以用来保存任何类型的数据。换句话说，每个变量仅仅是一个用于保存值的占位符而已。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> message;</span><br></pre></td></tr></table></figure>

<p>该变量可以用来保存任何值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> message = <span class="string">&quot;hi&quot;</span>; <span class="comment">//局部变量</span></span><br><span class="line">&#125;</span><br><span class="line">test();</span><br><span class="line">alert(message);</span><br></pre></td></tr></table></figure>

<p>使用一条语句定义多个变量</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> message = <span class="string">&quot;hi&quot;</span>,</span><br><span class="line">  found = fasle,</span><br><span class="line">  age = <span class="number">29</span>; <span class="comment">//提高可读性</span></span><br></pre></td></tr></table></figure>

<p>在严格模式下，不能定义名为 eval 或 arguments 的变量，否则会导致语法错误</p>
<ul>
<li>变量命名必须是以字母或是下标符号”_“或者”$”为开头</li>
<li>变量名长度不能超过 255 个字符</li>
<li>变量名中不允许使用空格，首个字母不能为数组</li>
<li>不用使用脚本语言中保留的关键字及保留符号作为变量名</li>
<li>变量名区分大小写</li>
</ul>
<h2 id="2-数据类型"><a href="#2-数据类型" class="headerlink" title="2.数据类型"></a>2.数据类型</h2><p>2.1 undefined 类型</p>
<p>只有一个值，即特殊的 undefined。在使用 var 声明变量但未对齐加以初始化时，这个变量的值就是 undefined</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> message;</span><br><span class="line">message == <span class="literal">undefined</span>; <span class="comment">//true. 未经初始化的值默认就是undefined</span></span><br></pre></td></tr></table></figure>

<p>typeof 对未初始化和未声明变量的返回都是 undefined 值</p>
<p>注意：没有必要把一个变量的值显示的设置成 undefined</p>
<p>2.2 Null 类型</p>
<p>Null 可以作为一个空对象的指针</p>
<p>undefined 的值是派生自 null 值的。</p>
<p>只要意在保存对象的变量还没有真正的保存对象，就应该明确地让该变量保存 null 值</p>
<p>2.3boolean</p>
<p>各种类型转化的规则</p>
<table>
<thead>
<tr>
<th>数据类型</th>
<th>转换为 true 的值</th>
<th>转换为 false 的值</th>
</tr>
</thead>
<tbody><tr>
<td>Boolean</td>
<td>True</td>
<td>False</td>
</tr>
<tr>
<td>String</td>
<td>任何非空字符串</td>
<td>空字符串</td>
</tr>
<tr>
<td>Number</td>
<td>任何非零数字值</td>
<td>0 和 NaN</td>
</tr>
<tr>
<td>Object</td>
<td>任何对象</td>
<td>Null</td>
</tr>
<tr>
<td>Undefined</td>
<td>/</td>
<td>false</td>
</tr>
</tbody></table>
<p>这种转换可以理解 if 语句</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> message = <span class="string">&#x27;hello world&#x27;</span>;</span><br><span class="line"><span class="keyword">if</span>(message)&#123;</span><br><span class="line">  alert(<span class="string">&#x27;value is true&#x27;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2.4Number</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> intNum = <span class="number">55</span>; <span class="comment">// 整数</span></span><br><span class="line"><span class="comment">// 8进制 第一位必须是 0 ，八进制数字序列（0 - 7)</span></span><br><span class="line"><span class="comment">// 八进制字面量在严格模式下是无效的，会导致js引擎错误</span></span><br><span class="line"><span class="keyword">var</span> oct = <span class="number">070</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//16进制 前两位必须是0x 后跟(0-9,以及A-F)</span></span><br><span class="line"><span class="keyword">var</span> hex = <span class="number">0x1f</span>;</span><br></pre></td></tr></table></figure>

<p>在进行算术计算时，所有的八进制和十六进制表示的数值最终都将会被转换成十进制</p>
<p>2.4.1 浮点数值</p>
<p>该数值中必须包含一个小数点，并且小数点后面必须有一位数字</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> floatNum = <span class="number">1.1</span>;</span><br></pre></td></tr></table></figure>

<p>由于保存浮点数值需要的内存空间时保存整数值的两倍，因此 ECMAScript 会不失时机地将浮点数值转换为整数值。如果浮点数值本身就是一个整数，那么也会转换成为整数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> floatNum = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">var</span> floatNum1 = <span class="number">10.0</span>;</span><br></pre></td></tr></table></figure>

<p>浮点数的最高精度时 17 位小数</p>
<p>2.4.2 NaN</p>
<p>Not a Number：非数值，这个数值用于表示一个本来要返回数值的操作数未返回数值的情况</p>
<p>NaN 的两个特点：</p>
<ul>
<li>任何涉及 NaN 的操作都会返回 NaN</li>
<li>NaN 与任何值都不相等</li>
</ul>
<p>ECMAScript 定义了 isNaN()函数，接收一个参数，参数可以时任何类型，不是数值的的值会直接转换为数值。</p>
<p>数值转换函数</p>
<ul>
<li>Number()</li>
<li>parseInt()</li>
<li>parseFloat()</li>
</ul>
<p>第一个函数，转型函数 Number 可以使用任何数据类型，另外两个函数专门用于把字符串转换成数值。</p>
<p>如果是 null，则返回 0</p>
<p>Undefined 返回 NaN</p>
<p>parseInt()解析八进制</p>
<p>多数情况下第二个参数也十分的重要</p>
<p>2.4.3 String 类型</p>
<p>字符字面量</p>
<p>String 数据类型包含一些特殊的字符字面量，也叫转译序列</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">\n      换行    newLine</span><br><span class="line">\t.     制表    table making</span><br><span class="line">\b.     退格    backsapce</span><br><span class="line">\r。    回车    resolve</span><br><span class="line">\f。    进纸</span><br><span class="line">\\.     斜杠</span><br></pre></td></tr></table></figure>

<p>字符串的特点</p>
<p>字符串一旦创建,它们的值就不能改变</p>
<p>数值、布尔值、对象和字符串值（每个字符串也都有一个 toString()方法，该方法返回字符串的一个副本)都有 toString()方法。null 和 undefined 没有</p>
<p>通过传递基数，toString（）可以输出以二进制</p>
<p>Object 类型</p>
<p>ECMAScript 中的对象其实就是一组数据和功能的集合。对象可以通过执行 new 操作符后跟要创建的对象类型的名称来创建。而创建 Object 实例并为其添加属性和方法，就可以创建自定义对象</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> o = <span class="keyword">new</span> <span class="built_in">Object</span>(); <span class="comment">// 如果不给构造函数传递参数，则可以省略后面的那一对括号。</span></span><br></pre></td></tr></table></figure>

<p>object 类型所具有的任何属性和方法同样也存在与更具体的对象中<br>每个实例都具有下列的属性和方法</p>
<ul>
<li>constructor:保存当前用于创建当前对象的函数。对于前面李子来说，构造函数(constructor）就是 Object</li>
<li>hasOwnProperty：用于检查给定的属性在当前对象实例中是否存在。</li>
<li>isPrototypeOf(object)：用于检查传入对象是否是当前对象的原型</li>
<li>propertylsEnumerable(propertyName):用于检查给定的属性是否能够使用 for..in 语句来枚举</li>
<li>toLocalString():返回对象的字符串表示，该字符串与执行环境的地区对应</li>
<li>toString（）:返回对象的字符串的表示</li>
<li>valueOf():返回对象的字符串、数值或布尔值</li>
</ul>
<p>隐式转换</p>
<p>首先要清楚 js 中存在两个方法 valueof 和 testing，它们存在于最顶层的原型 Object.prototype 上，也就是说我们可以通过原型链访问到这两个方法，它们适用于 ToPrimitive 也就是转换为原始值。valueof 函数返回的是本身（基础类型则是原始值，引用类型则是 this);toString 函数在基础类型中返回的是字符串化的原始值，在引用类型中则是返回当前类型。值得注意的是，js 对 valueof 和 tostring 进行了不同的实现</p>
<p>在进行隐式转换的时，总会先调用 valueof，如果返回值不是原始值的话，又会继续调用 toString 方法。对于非引用类型，valueOf 返回的则是原始值，引用类型则是返回它本身。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">  <span class="function"><span class="title">valueOf</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;valueOf&quot;</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="function"><span class="title">toString</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;toString&quot;</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>部分内置对象实现 valueof 和 tostring 的方法</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>ValueOf</th>
<th>toString</th>
</tr>
</thead>
<tbody><tr>
<td>Number(123)</td>
<td>123</td>
<td>‘123’</td>
</tr>
<tr>
<td>String(‘abc123’)</td>
<td>‘abc123’</td>
<td>‘ab123’</td>
</tr>
<tr>
<td>Boolean(‘666’)</td>
<td>True</td>
<td>True</td>
</tr>
<tr>
<td>Date()</td>
<td>时间戳</td>
<td>日期字符串</td>
</tr>
<tr>
<td>Array([1,2,3])</td>
<td>This</td>
<td>‘1,2,3’(相当于调用 join(‘,’))</td>
</tr>
<tr>
<td>Object({})</td>
<td>This</td>
<td>‘[object object]’</td>
</tr>
<tr>
<td>Function(()=&gt;{})</td>
<td>This</td>
<td>‘() =&gt; {}’</td>
</tr>
<tr>
<td>RegExp(‘1’)</td>
<td>This</td>
<td>‘/1/‘</td>
</tr>
</tbody></table>
<p>例子：</p>
<p><strong>例一</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> result = <span class="number">100</span> + <span class="literal">true</span> + <span class="number">21.2</span> + <span class="literal">null</span> + <span class="literal">undefined</span> + <span class="string">&quot;tencent&quot;</span> + [] + <span class="number">9</span> + <span class="literal">false</span>;</span><br><span class="line"><span class="built_in">console</span>.log(result);</span><br><span class="line"><span class="built_in">console</span>.log([] == <span class="literal">false</span>);</span><br><span class="line"><span class="built_in">console</span>.log(![] == <span class="literal">false</span>);</span><br><span class="line"></span><br><span class="line">先重温：</span><br><span class="line"><span class="number">1.</span>基本数据类型：number string boolean <span class="literal">null</span> <span class="literal">undefined</span> symbol bigint</span><br><span class="line"><span class="number">2.</span>引用数据类型：object <span class="function"><span class="keyword">function</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">解题：</span></span><br><span class="line"><span class="function">1.其他类型会转换为<span class="title">number</span>类型（对象先转换为<span class="title">string</span> -&gt; <span class="title">number</span>)</span></span><br><span class="line"><span class="function">- <span class="title">Number</span>(<span class="params">[val]</span>)</span></span><br><span class="line"><span class="function">- <span class="title">parseInt</span>(<span class="params">[val]</span>) <span class="title">parseFloat</span>(<span class="params">[val]</span>)</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">2.隐式转换（浏览器内默认先转换为<span class="title">number</span>在进行计算）</span></span><br><span class="line"><span class="function">- <span class="title">isNaN</span>(<span class="params">[val]</span>)</span></span><br><span class="line"><span class="function">- 在+号左右的字符串被视为字符串拼接而不是运算符</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">3.类型相同</span></span><br><span class="line"><span class="function">- </span>&#123;&#125; == &#123;&#125;  <span class="comment">// false ，因为对象比较是堆内存地址比较</span></span><br><span class="line">- [] == [] <span class="comment">// false</span></span><br><span class="line">- <span class="literal">NaN</span> == <span class="literal">NaN</span> <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="number">4.</span>类型不同</span><br><span class="line">- <span class="literal">null</span> == <span class="literal">undefined</span> <span class="comment">// true</span></span><br><span class="line">- <span class="literal">null</span> === <span class="literal">undefined</span> <span class="comment">// false</span></span><br><span class="line"><span class="literal">null</span>和<span class="literal">undefined</span>和其他都不等</span><br><span class="line">string == object，要把对象转换为字符串</span><br><span class="line">其余先转为number类型在进行比较</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> result = <span class="number">100</span> + <span class="literal">true</span>(<span class="number">1</span>) + <span class="number">21.2</span> + <span class="literal">null</span>(<span class="number">0</span>) + <span class="literal">undefined</span>(<span class="literal">NaN</span>) + <span class="string">&quot;tencent&quot;</span> + [](<span class="string">&#x27;&#x27;</span>) + <span class="number">9</span> + <span class="literal">false</span>(<span class="string">&#x27;false&#x27;</span>)</span><br><span class="line"><span class="built_in">Number</span>(<span class="literal">undefined</span>) <span class="comment">// NaN</span></span><br><span class="line"></span><br><span class="line">[] == <span class="literal">false</span></span><br><span class="line"><span class="literal">true</span></span><br><span class="line">![] == <span class="literal">false</span></span><br><span class="line"><span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log([] == <span class="literal">false</span>);</span><br><span class="line"><span class="built_in">Number</span>([]) <span class="comment">// 0</span></span><br><span class="line"><span class="literal">false</span> <span class="comment">// 0</span></span><br><span class="line"><span class="number">0</span> == <span class="number">0</span> <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(![] == <span class="literal">false</span>);</span><br><span class="line"><span class="comment">// 运算符优先级更高,!非 结果boolean</span></span><br><span class="line">![] <span class="comment">// false</span></span><br><span class="line"><span class="comment">// false、false类型相同</span></span><br><span class="line"><span class="literal">false</span> == <span class="literal">false</span> <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p><strong>例二</strong>：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = ?</span><br><span class="line"><span class="keyword">if</span> (a == <span class="number">1</span> &amp;&amp; a == <span class="number">2</span> &amp;&amp; a == <span class="number">3</span>) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="number">1</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>解题</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span>对象会隐式调用toString</span><br><span class="line"><span class="keyword">let</span> a = &#123;</span><br><span class="line">  i:<span class="number">0</span>,</span><br><span class="line">  <span class="function"><span class="title">toString</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> ++<span class="built_in">this</span>.i</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span>方法会直接在一个对象上定义个新属性，或者修改一个对象的现有属性，并返回此对象</span><br><span class="line"><span class="keyword">let</span> i =<span class="number">0</span></span><br><span class="line"><span class="built_in">Object</span>.defineProperty(<span class="built_in">window</span>,<span class="string">&#x27;a&#x27;</span>,&#123;</span><br><span class="line">  <span class="function"><span class="title">get</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> ++i;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h2 id="3-操作符"><a href="#3-操作符" class="headerlink" title="3.操作符"></a>3.操作符</h2><p>描述一组用于操作数据值的操作符</p>
<ul>
<li>算术操作符</li>
<li>位操作符</li>
<li>关系操作符</li>
<li>相等操作符</li>
</ul>
<p><strong>3.1.一元操作符</strong></p>
<p>只能操作一个值的操作符</p>
<p>递增、递减操作符</p>
<ul>
<li><p>前置型</p>
</li>
<li><pre><code class="javascript">var age = 29;
age = age + 1 == ++age;

var age = 29;
var anotherAge = --age + 2;
alert(age); // 28
alert(anotherAge); // 30

// 只要是前缀操作符，变量的值都会在语句被求值之前改变（在计算机科学中，这通常被称为具有副作用）
// 因为前置递增和递减操作与执行语句的优先级相等，因此整个语句会从左到右被求值
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">&#96;&#96;&#96;&#96;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">- 后置型</span><br><span class="line"></span><br><span class="line">- &#96;&#96;&#96;javascript</span><br><span class="line">  &#x2F;&#x2F; 后缀版与前缀版的区别：后缀版递增和递减</span><br><span class="line">  var age &#x3D; 29;</span><br><span class="line">  age++;   &#x2F;&#x2F; 把递增操作符放在变量后面并不会改变语句的结果</span><br><span class="line"></span><br><span class="line">  var num1 &#x3D; 2;</span><br><span class="line">  var num2 &#x3D; 20;</span><br><span class="line">  var num3 &#x3D; num1-- + num2;  &#x2F;&#x2F; 22</span><br><span class="line">  var num4 &#x3D; num1 + num2;    &#x2F;&#x2F; 21</span><br><span class="line">&#96;&#96;&#96;&#96;</span><br><span class="line"></span><br><span class="line">- 隐式转换成 number</span><br><span class="line"></span><br><span class="line">- &#96;&#96;&#96;javascript</span><br><span class="line">  var s1 &#x3D; &quot;2&quot;;</span><br><span class="line">  var s2 &#x3D; &quot;z&quot;;</span><br><span class="line">  var b &#x3D; false;</span><br><span class="line">  var f &#x3D; 1.1;</span><br><span class="line">  var o &#x3D; &#123;</span><br><span class="line">    valueof: function () &#123;</span><br><span class="line">      return -1;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  s1++; &#x2F;&#x2F; 3</span><br><span class="line">  s2++; &#x2F;&#x2F; NaN</span><br><span class="line">  b++; &#x2F;&#x2F; 1</span><br><span class="line">  f--; &#x2F;&#x2F; 0.10000000000009（由于浮点舍入错误所致）</span><br><span class="line">  o--; &#x2F;&#x2F; -2</span><br></pre></td></tr></table></figure>
</code></pre>
</li>
</ul>
<p><strong>3.2 一元加和减操作符</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> num = <span class="number">25</span>;</span><br><span class="line">num = +num; <span class="comment">// 25</span></span><br></pre></td></tr></table></figure>

<p>对非数值应用一元加操作符</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s1 = <span class="string">&#x27;01&#x27;</span></span><br><span class="line"><span class="keyword">var</span> s2 = <span class="string">&#x27;1.1&#x27;</span></span><br><span class="line"><span class="keyword">var</span> s3 = <span class="string">&#x27;z&#x27;</span></span><br><span class="line"><span class="keyword">var</span> b = <span class="literal">false</span></span><br><span class="line"><span class="keyword">var</span> f = <span class="number">1.1</span></span><br><span class="line"><span class="keyword">var</span> o = &#123;</span><br><span class="line">  valueOf:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> -<span class="number">1</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">s1 = +s1 <span class="comment">// 1</span></span><br><span class="line">s2 = +s2 <span class="comment">// 1.1</span></span><br><span class="line">s3 = +s3 <span class="comment">// NaN</span></span><br><span class="line">b = +b;  <span class="comment">// 0</span></span><br><span class="line">f = +f.  <span class="comment">// 1.1</span></span><br><span class="line">o = +o.  <span class="comment">// -1</span></span><br><span class="line"><span class="comment">// 要是 - 的话将转换为负数</span></span><br></pre></td></tr></table></figure>

<p><strong>3.3 位操作符</strong></p>
<p>按内存中表示数值的位来操作数值</p>
<p><strong>3.4 布尔操作符</strong></p>
<p>非（not）、与（and）、或（or）</p>
<p>1.逻辑非</p>
<p>无论什么数据类型，都将返回一个布尔值。效果就是：无论这个值是什么类型，先返回一个布尔值，然后对其取反</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">!<span class="literal">false</span>; <span class="comment">// true</span></span><br><span class="line">!<span class="string">&quot;blue&quot;</span>; <span class="comment">// false</span></span><br><span class="line">!<span class="number">0</span>; <span class="comment">// true</span></span><br><span class="line">!<span class="literal">NaN</span>; <span class="comment">// true</span></span><br><span class="line">!<span class="string">&quot;&quot;</span>; <span class="comment">// true</span></span><br><span class="line">!<span class="number">1234</span>; <span class="comment">// false</span></span><br><span class="line"><span class="comment">// 实际上会模拟Boolean（）转型函数的行为。</span></span><br></pre></td></tr></table></figure>

<p>2.逻辑与(&amp;&amp;)</p>
<p>从左到右，如果为 false 则返回</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> res = <span class="literal">true</span> &amp;&amp; <span class="literal">false</span>; <span class="comment">// false</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="literal">false</span> &amp;&amp; <span class="literal">true</span>; <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<p>3.逻辑或(||)</p>
<p>从左到右只要遇到 true 就返回</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> res = <span class="literal">true</span> || <span class="literal">false</span>; <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p><strong>3.5 关系运算符</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> res = <span class="number">5</span> &gt; <span class="number">3</span>; <span class="comment">// true</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="number">5</span> &lt; <span class="number">3</span>; <span class="comment">// false</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="string">&quot;Bob&quot;</span> &lt; <span class="string">&quot;aaaaaa&quot;</span>; <span class="comment">// true   B的字符编码为66。字母a的字符编码是97</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="string">&quot;Bob&quot;</span>.toLowerCase() &lt; <span class="string">&quot;alphabet&quot;</span>.toLowerCase(); <span class="comment">// false</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="string">&quot;23&quot;</span> &lt; <span class="string">&quot;3&quot;</span>; <span class="comment">// true.   “2”的编码是50。&quot;3&quot;的编码是51</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="string">&quot;23&quot;</span> &lt; <span class="number">3</span>; <span class="comment">// false</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="string">&quot;a&quot;</span> &lt; <span class="number">3</span>; <span class="comment">// false 因为&quot;a&quot;被转换成了NaN</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="literal">NaN</span> &lt; <span class="number">3</span>; <span class="comment">// false</span></span><br><span class="line"><span class="keyword">var</span> res = <span class="literal">NaN</span> &gt;= <span class="number">3</span>; <span class="comment">// false.    任何数与NaN比较都是false</span></span><br></pre></td></tr></table></figure>

<p><strong>4.逗号操作符</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> num1 = <span class="number">1</span>,</span><br><span class="line">  num2 = <span class="number">2</span>,</span><br><span class="line">  num3 = <span class="number">3</span>; <span class="comment">// 逗号操作符声明了多个变量，但是除此之外，逗号操作符还可以用来赋值</span></span><br><span class="line"><span class="keyword">var</span> num = (<span class="number">5</span>, <span class="number">4</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">0</span>); <span class="comment">// num = 0 总会返回表达式中的最后一项</span></span><br></pre></td></tr></table></figure>

<h2 id="4-语句"><a href="#4-语句" class="headerlink" title="4.语句"></a>4.语句</h2><p>语句定义了 ECMAScript 中的主要语法，语句通常使用一或多个关键字来完成给定任务。</p>
<p><strong>4.1 if 语句</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (condition) statement1 <span class="keyword">else</span> statement2</span><br></pre></td></tr></table></figure>

<p><strong>4.2 do-while 语句</strong></p>
<p>后测试循环语句，即只有在循环体中的代码执行之后，才会测试出口条件。在对条件表达式求值之前，循环体内的代码至少被执行一次</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">  i += <span class="number">2</span>;</span><br><span class="line">&#125; <span class="keyword">while</span> (i &lt; <span class="number">10</span>);</span><br><span class="line">alert(i); <span class="comment">// 12</span></span><br></pre></td></tr></table></figure>

<p><strong>4.3 while 语句</strong></p>
<p>前测试循环语句，在循环体内的代码被执行之前，就会对出口条件求值</p>
<p><strong>4.4 for 语句</strong></p>
<p>前测试循环语句</p>
<p><strong>4.5 for-in 语句</strong></p>
<p>一种精准的迭代语句，可以用来枚举对象的属性。</p>
<p><strong>4.6 label 语句</strong></p>
<p>使用 label 语句可以在代码中添加标签</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">label:statement</span><br><span class="line"></span><br><span class="line">start:<span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; count; i++)&#123;</span><br><span class="line">  alert(i)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 这个例子定义的start标签可以将来由break或continue引用</span></span><br><span class="line">举一个比较典型的例子，看完后即明白 Label 的应用：（未添加 Label）</span><br><span class="line">        <span class="keyword">var</span> num = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span> ; i &lt; <span class="number">10</span> ; i++)&#123;</span><br><span class="line">             <span class="keyword">for</span> (<span class="keyword">var</span> j = <span class="number">0</span> ; j &lt; <span class="number">10</span> ; j++)&#123;</span><br><span class="line">                  <span class="keyword">if</span>( i == <span class="number">5</span> &amp;&amp; j == <span class="number">5</span> )&#123;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                  &#125;</span><br><span class="line">             num++;</span><br><span class="line">             &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        alert(num); <span class="comment">// 循环在 i 为5，j 为5的时候跳出 j循环，但会继续执行 i 循环，输出 95</span></span><br><span class="line"></span><br><span class="line">对比使用了 Label 之后的程序：（添加 Label 后）</span><br><span class="line">    <span class="keyword">var</span> num = <span class="number">0</span>;</span><br><span class="line">    outPoint:</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span> ; i &lt; <span class="number">10</span> ; i++)&#123;</span><br><span class="line">         <span class="keyword">for</span> (<span class="keyword">var</span> j = <span class="number">0</span> ; j &lt; <span class="number">10</span> ; j++)&#123;</span><br><span class="line">              <span class="keyword">if</span>( i == <span class="number">5</span> &amp;&amp; j == <span class="number">5</span> )&#123;</span><br><span class="line">                    <span class="keyword">break</span> outPoint;</span><br><span class="line">              &#125;</span><br><span class="line">         num++;</span><br><span class="line">         &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    alert(num); <span class="comment">// 循环在 i 为5，j 为5的时候跳出双循环，返回到outPoint层继续执行，输出 55</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><strong>4.7 break 和 continue 语句</strong></p>
<p>用于在循环中精确地控制代码的执行，break 会立即退出循环，强制执行循环后面的语句。而 continue 语句也是立即退出循环，但退出循环后会继续从循环的顶部继续执行</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> num = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i =<span class="number">1</span>; i&lt;<span class="number">10</span>; i++)&#123;</span><br><span class="line">  <span class="keyword">if</span>(i % <span class="number">5</span> == <span class="number">0</span>)&#123;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  num++;</span><br><span class="line">&#125;</span><br><span class="line">alert(num)  <span class="comment">// 4</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> num = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i =<span class="number">1</span>; i&lt;<span class="number">10</span>; i++)&#123;</span><br><span class="line">  <span class="keyword">if</span>(i % <span class="number">5</span> == <span class="number">0</span>)&#123;</span><br><span class="line">    <span class="keyword">continue</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  num++;</span><br><span class="line">&#125;</span><br><span class="line">alert(num)  <span class="comment">// 8</span></span><br><span class="line">当变量等于i等于<span class="number">5</span>时，循环会在num再次递增之前退出，但接下来执行的是下一次循环，即i的值等于<span class="number">6</span>的循环。</span><br></pre></td></tr></table></figure>

<p><strong>4.8 with 语句</strong></p>
<p>with 语句的作用是将代码的作用域设置到一个特定的对象中。with 语法</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">with</span> (expression) statement;</span><br></pre></td></tr></table></figure>

<p>定义 with 语句的目的主要是为了简化多次编写同一个对象的工作</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> qs = location.search.substring(<span class="number">1</span>);</span><br><span class="line"><span class="keyword">var</span> hostName = location.hostname;</span><br><span class="line"><span class="keyword">var</span> url = location.href;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用 with语句可以改成</span></span><br><span class="line"><span class="keyword">with</span> (location) &#123;</span><br><span class="line">  <span class="keyword">var</span> qs = search.substring(<span class="number">1</span>);</span><br><span class="line">  <span class="keyword">var</span> hostname = hostname;</span><br><span class="line">  <span class="keyword">var</span> url = href;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>使用 with 语句关联了 location 对象，这意味着在 with 语句的代码块内部，每个变量首先被认为是一个局部变量，</p>
<p><strong>4.9 switch 语句</strong></p>
<p>流控制语句</p>
<p>switch 语句在比较值时使用的是全等操作符，因此不会发生类型转换</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span> (<span class="string">&quot;hello world&quot;</span>) &#123;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&quot;hello&quot;</span> + <span class="string">&quot;world&quot;</span>:</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>case 条件的值不需要是敞亮也可以是变量或表达式</p>
<p>switch 语句在比较每个条件的值时会使用全等操作符，因此不会强制的转换数据类型</p>
<h2 id="4-函数"><a href="#4-函数" class="headerlink" title="4.函数"></a>4.函数</h2><p>注意：只要碰到 return 语句，函数就会立即停止执行并退出。</p>
<p>严格模式下对函数的限制</p>
<ul>
<li><p>函数不能以 eval 或 arguments 作为名称</p>
</li>
<li><p>函数的参数不能叫 eval 或 arguments</p>
</li>
<li><p>两个命名参数不能拥有同一个名称</p>
</li>
</ul>
<p>小结：js 核心语言特性在 ECMA-262 中以伪语言 ECMAScript 的形式来定义。ECMAScript 包含所有基本语法、操作符、数据类型和对象，能完成基本的计算任务，但没有提供获得输入和产生输入的机制。理解 ECMAScript 复杂的细节是完全理解浏览器中 js 的关键。下面了解基本的 ECMAScript</p>
<ul>
<li>基本类型包括：undefined,null,boolean,number,string,symbol</li>
<li>与其他语言不通，ECMAScript 不区分整数和浮点值，只有 Number 一种数值数据类型</li>
<li>Object 是一种复杂数据类型，它是这门语言中所有对象的基类</li>
</ul>

      
    </div>

    
    
    
      <div>
          
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://skycoin.gitee.io/codeblog/2021/02/27/%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%86%85%E5%AD%98/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4083356047,3551369852&fm=26&gp=0.jpg">
      <meta itemprop="name" content="若说">
      <meta itemprop="description" content="立志完成前端知识体系的架构">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="若水的前端博客">
    </span>
      <header class="post-header">
      
        <i class="fa fa-thumb-tack"></i>
        <font color=7D26CD>置顶</font>
      
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/codeblog/2021/02/27/%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%86%85%E5%AD%98/" class="post-title-link" itemprop="url">Javascript基础（三）：javascript的变量、作用域与内存</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-27 10:14:52" itemprop="dateCreated datePublished" datetime="2021-02-27T10:14:52+08:00">2021-02-27</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-15 09:24:35" itemprop="dateModified" datetime="2021-04-15T09:24:35+08:00">2021-04-15</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/codeblog/categories/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">前端框架</span></a>
                </span>
            </span>

          
            <span id="/codeblog/2021/02/27/%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%86%85%E5%AD%98/" class="post-meta-item leancloud_visitors" data-flag-title="Javascript基础（三）：javascript的变量、作用域与内存" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/codeblog/2021/02/27/%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%86%85%E5%AD%98/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/codeblog/2021/02/27/%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%86%85%E5%AD%98/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>[toc]</p>
<h2 id="1-通过变量使用原始值与引用值"><a href="#1-通过变量使用原始值与引用值" class="headerlink" title="1.通过变量使用原始值与引用值"></a>1.通过变量使用原始值与引用值</h2><h3 id="1-1-原始值与引用值"><a href="#1-1-原始值与引用值" class="headerlink" title="1.1 原始值与引用值"></a>1.1 原始值与引用值</h3><p>ES 变量可以包含两种不同类型的数据：原始值和引用值</p>
<p>原始值：最简单的数据</p>
<p>引用值：由多个值构成的对象</p>
<p>Tips:在把一个值赋给变量时，js 引擎必须确定这个值时原始值还是引用值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 原始值</span></span><br><span class="line"><span class="literal">undefined</span></span><br><span class="line"><span class="literal">null</span></span><br><span class="line">boolean</span><br><span class="line">number</span><br><span class="line">string</span><br><span class="line">symbol</span><br><span class="line"></span><br><span class="line"><span class="comment">// 引用值时保存在内存中的对象</span></span><br><span class="line">js不允许直接访问内存位置，因此不能直接操作对象所在的内存空间</span><br><span class="line">在操作对象时，实际上的操作时对该对象的引用，而非实际的对象本身</span><br></pre></td></tr></table></figure>

<p>补充</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">js中的内存分为堆内存和栈内存</span><br><span class="line">堆内存：存储引用类型值</span><br><span class="line">栈内存：提供js代码执行的环境和存储基本类型</span><br><span class="line"></span><br><span class="line">堆内存释放：让所有堆内存空间地址的变量赋值为<span class="literal">null</span>即可</span><br><span class="line">栈内存释放：</span><br><span class="line"><span class="number">1</span>。函数执行完成，当前形成的栈内存中，某些内容被栈内存以外的变量占用了</span><br><span class="line"><span class="number">2.</span>全局栈内存只有在页面关闭的时候才会释放掉</span><br></pre></td></tr></table></figure>

<h3 id="1-1-1-动态属性"><a href="#1-1-1-动态属性" class="headerlink" title="1.1.1 动态属性"></a>1.1.1 动态属性</h3><p>原始值和引用值定义方式类似，都是创建一个变量，然后赋值。不过在变量保存这个值之后，可以对这个值的操作不同。</p>
<ul>
<li>对于引用值来说，可以随时添加、修改和删除其属性的方法</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> person = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">person.name = <span class="string">&quot;nick&quot;</span>; <span class="comment">// 给对象添加一个name属性</span></span><br></pre></td></tr></table></figure>

<ul>
<li>原始值不能有属性</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> name = <span class="string">&quot;nick&quot;</span>;</span><br><span class="line">name.age = <span class="number">27</span>; <span class="comment">// undefined</span></span><br><span class="line"><span class="comment">// 原始类型的初始化可以使用原始字面量的形式。</span></span><br></pre></td></tr></table></figure>

<h3 id="1-1-2-复制值"><a href="#1-1-2-复制值" class="headerlink" title="1.1.2 复制值"></a>1.1.2 复制值</h3><p>除了存储方式不同，原始值和引用值在通过变量赋值时也有所不同。</p>
<ul>
<li>在通过变量把一个原始值赋值到另一个变量时，原始值也会被复制到新变量的位置</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num1 = <span class="number">5</span>;</span><br><span class="line"><span class="keyword">let</span> num2 = num1;</span><br><span class="line"><span class="comment">// 这两个变量可以单独使用，互不干扰</span></span><br></pre></td></tr></table></figure>

<ul>
<li>在把引用值从一个变量赋给另一个变量时，存储在变量中的值也会被复制到新变量所在的位置，区别在于，这里复制的值实际上是一个指针，它指向存储在堆内存中的对象。操作完成后，两个变量实际上指向同一个对象，因此一个对象变化另一个对象也会变化</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj1 = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">obj1.name = <span class="string">&quot;nick&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> obj2 = obj1;</span><br><span class="line">obj2.name; <span class="comment">// nick</span></span><br></pre></td></tr></table></figure>

<h3 id="1-1-3-传递参数"><a href="#1-1-3-传递参数" class="headerlink" title="1.1.3 传递参数"></a>1.1.3 传递参数</h3><p>es 中所有的函数都是按值传递的。函数外的值会被复制到函数内部的参数中，就像从一个变量复制到另一个变量一样。</p>
<p>按值传递参数时，值会被复制到一个局部变量（即一个命名参数，或者用 es 的话说，就像 arguments 对象中的一个槽位）</p>
<ul>
<li>传递原始值的时候</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">addTen</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  num += <span class="number">10</span>;</span><br><span class="line">  <span class="keyword">return</span> num;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> count = <span class="number">20</span>;</span><br><span class="line"><span class="keyword">let</span> result = addTen(count); <span class="comment">// count = 20   result = 30 没有变化</span></span><br></pre></td></tr></table></figure>

<ul>
<li>传递引用值的时候</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">setName</span>(<span class="params">obj</span>) </span>&#123;</span><br><span class="line">  obj.name = <span class="string">&quot;nick&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> person = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">setName(person);</span><br><span class="line"><span class="built_in">console</span>.log(person.name); <span class="comment">// nick</span></span><br><span class="line"><span class="comment">// 在函数内部，obj和perosn都指向同一个对象。所以即使对象时按值传进函数的，obj也会通过引用访问对象。当函数内给obj设置了name属性时，函数外部的对象保存在全局作用的堆内存上</span></span><br></pre></td></tr></table></figure>

<h3 id="1-1-4-确定类型"><a href="#1-1-4-确定类型" class="headerlink" title="1.1.4 确定类型"></a>1.1.4 确定类型</h3><ul>
<li>原始值</li>
</ul>
<p>typeof 操作符最适合来判断一个变量是否为原始类型，如果值是对象或者 null,那么 typeof 返回 object，如果想知道是什么类型的对象就需要看引用值</p>
<ul>
<li>引用值</li>
</ul>
<p>使用 instanceof 操作符</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">result = variable instaceof <span class="title">constructor</span></span><br><span class="line"></span><br><span class="line">// 如果变量给定引用类型（由其原型链决定）的实例，则<span class="title">instanceof</span>操作符返回<span class="title">true</span></span><br><span class="line"><span class="title">person</span> <span class="title">instanceof</span> <span class="title">Object</span>   // 变量<span class="title">person</span>是<span class="title">object</span>吗</span><br><span class="line"><span class="title">colors</span> <span class="title">instanceof</span> <span class="title">Array</span>    // 变量<span class="title">colors</span>是<span class="title">Array</span>吗</span><br><span class="line"><span class="title">pattern</span> <span class="title">instanceof</span> <span class="title">RegExp</span>  // 变量<span class="title">pattern</span>是<span class="title">RegExp</span></span><br></pre></td></tr></table></figure>

<p>所有引用值都是 Object 的实例，因此通过 instanceof 操作符检测任何引用值和 object 构造函数都会返回 true。</p>
<h4 id="1-1-5-js-代码运行的过程"><a href="#1-1-5-js-代码运行的过程" class="headerlink" title="1.1.5 js 代码运行的过程"></a>1.1.5 js 代码运行的过程</h4><p>Js 是动态语言，任何一段代码在执行之前都需要编译，它跟传统的语言不同，它不是提前编译的，编译的结果也不能在分布式系统中进行移植</p>
<p>但是 js 引擎进行编译的步骤和传统的编译语言非常类似</p>
<p><strong>传统的编译</strong></p>
<ul>
<li>分词/词法分析</li>
</ul>
<p>这个过程将由字符串组成的字符串分解成有意义的代码块，这些代码块称为词法单元</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">e.g  <span class="keyword">var</span> a = <span class="number">2</span>;</span><br><span class="line">通过被解析成  <span class="keyword">var</span> 、a、=、<span class="number">2</span>、;</span><br><span class="line">空格是否被当做此法单元，取决于空格在这门语言中是否具有意义</span><br></pre></td></tr></table></figure>

<ul>
<li>解析/语法分析</li>
</ul>
<p>这个过程是将词法单元流（数组）转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树（抽象语法树）</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">2</span>;</span><br><span class="line">通过特定方法将<span class="keyword">var</span>=<span class="number">2</span>的AST转化为一组机器指令，用来创建一个叫做a的变量，并将一个值存储到a中</span><br></pre></td></tr></table></figure>

<p><strong>js 编译</strong></p>
<p>js 的编译步骤和传统还是非常相似的，只是某些环节比较复杂，这里说一下预编译，其他三个步骤同传统的编译</p>
<ul>
<li>分词/词法分析</li>
<li>解析/语法分析</li>
<li>预编译</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params">b</span>) </span>&#123;</span><br><span class="line">  alert(b);</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">b</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    alert(b);</span><br><span class="line">  &#125;</span><br><span class="line">  b();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">a(<span class="number">1</span>);</span><br></pre></td></tr></table></figure>

<p>答案先不说，现在看具体的预编译过程</p>
<p>1.预编译–全局</p>
<ul>
<li><p>创建 Global Object 对象（GO)</p>
<p>2.查找变量声明</p>
</li>
<li><p>如果 Go 上还没有该属性，则添加属性，值为 undefined</p>
</li>
<li><p>如果 Go 上已经有该属性，则不做任何处理</p>
<p>3.查找函数声明</p>
</li>
<li><p>如果 Go 上还没有 foo 属性，则把函数赋值给 foo 属性</p>
</li>
<li><p>如果 Go 上已经存在 foo 属性，则直接覆盖</p>
</li>
</ul>
<p>预编译–函数</p>
<ul>
<li>函数运行前的一瞬间，生成 Activation Object，简称 AO</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params">b</span>) </span>&#123;</span><br><span class="line">  alert(b);</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">b</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    alert(b);</span><br><span class="line">  &#125;</span><br><span class="line">  b();</span><br><span class="line">&#125;</span><br><span class="line">a(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 分析如下</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * 1. 创建GO对象（包含JS全局对象的内置对象Math、String、Date、etc）</span></span><br><span class="line"><span class="comment"> * 2. 查找变量声明，没有</span></span><br><span class="line"><span class="comment"> * 3. 查找函数声明，定义函数a, GO = &#123;a: function () &#123;&#125;&#125;</span></span><br><span class="line"><span class="comment"> * 4. 执行a(1)</span></span><br><span class="line"><span class="comment"> * // 以下为函数a运行前的编译</span></span><br><span class="line"><span class="comment"> * 5. 创建活动对象AO  AO=&#123;this, arguments&#125;</span></span><br><span class="line"><span class="comment"> * 6. 分析形参 AO = &#123;this, arguments, b: undefined&#125;</span></span><br><span class="line"><span class="comment"> * 7. 接收实参 AO = &#123;this, arguments, b: 1&#125;</span></span><br><span class="line"><span class="comment"> * 8. 分析变量声明 AO = &#123;this, arguments, b: 1&#125;</span></span><br><span class="line"><span class="comment"> * 9. 分析函数声明 </span></span><br><span class="line"><span class="comment">     AO = &#123;</span></span><br><span class="line"><span class="comment">         this</span></span><br><span class="line"><span class="comment">         argunments,</span></span><br><span class="line"><span class="comment">         b: function () &#123;&#125;</span></span><br><span class="line"><span class="comment">     &#125;</span></span><br><span class="line"><span class="comment"> </span></span><br><span class="line"><span class="comment"> * // 执行</span></span><br><span class="line"><span class="comment"> * alert(b)  // function () &#123; ... &#125;</span></span><br><span class="line"><span class="comment"> * b()   // function () &#123; ... &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<h3 id="1-2-执行上下文与作用域"><a href="#1-2-执行上下文与作用域" class="headerlink" title="1.2 执行上下文与作用域"></a>1.2 执行上下文与作用域</h3><p>变量或函数的上下文决定了它们可以访问哪些数据，以及他们的行为。每个上下文都有一个关联的变量对象，而这个上下文中定义的所有变量和函数都存在于这个对象上</p>
<p>全局上下文是最外层的上下文。根据 es 实现的宿主环境，表示全局上下文的对象可能不一样。在浏览器中，全局上下文就是我们所说的 window 对象，因此所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法。使用 let 和 const 的顶级声明不会定义在全局上下文中，但在作用域解析上效果是一样的。</p>
<p>每个函数调用都有自己的上下文。当代码执行流进入函数时，函数的上下文被推到一个上下文栈上。在函数执行完之后，上下文栈会弹出该函数上下文，将控制权返还给之前的执行上下文。es 程序的执行流就是通过这个上下文栈进行控制的</p>
<p>上下文中的代码在执行的时候，会创建变量对象的一个作用域链。这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域链的最前端。如果上下是函数，则其活动对象用做变量对象。活动对象最初只有一个定义变量：arguments。作用域链中的下一个变量对象来自包含上下文，在下一个对象来自在下一个包含上下文，全局的上下文的变量对象始终是作用域链的最后一个变量对象</p>
<p>代码执行时的标识符解析时通过沿作用域链逐级搜索表示名称完成的，搜索过程始终从作用域链的最前端开始，然后逐级往后，直到找到标识符</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> color = <span class="string">&quot;blue&quot;</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">changeColor</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (color === <span class="string">&quot;blue&quot;</span>) &#123;</span><br><span class="line">    color = <span class="string">&quot;red&quot;</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    color = <span class="string">&quot;blue&quot;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">changeColor();</span><br><span class="line"><span class="comment">//函数changeColor()的作用域链包含两个对象：一个是它自己的变量对象（就是定义arguments对象那个)，另一个就是全局上下文的变量对象。这个函数内部之所以能够访问变量color，就是因为可以在作用域链中找到他</span></span><br></pre></td></tr></table></figure>

<p>此外，局部作用域中定义的变量可用于在局部上下文中替换全局变量</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> color = <span class="string">&quot;blue&quot;</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">changeColor</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> anotherColor = <span class="string">&quot;red&quot;</span>;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">swapColors</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> tempColor = antherColor;</span><br><span class="line">    antherColor = color;</span><br><span class="line">    color = tempColor;</span><br><span class="line">    <span class="comment">//这里可以访问color、anotherColor和tempColor</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 这里可以访问color和anotherColor，但访问不到tempColor</span></span><br><span class="line">  swapColors();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 这里只能访问color</span></span><br><span class="line"></span><br><span class="line">changeColor();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 这个例子告诉我们，内部上下文可以通过作用域链访问外部上下文中的一切，但外部的上下文，无法访问内部上下文的任何东西。</span></span><br></pre></td></tr></table></figure>

<p>1.2.1 详解：执行上下文与可执行代码</p>
<p>可执行代码的类型</p>
<ul>
<li>全局代码：例如加载外部的 js 文件或者本地标签内的代码。全局代码不包过 function 体内的代码</li>
<li>函数代码：function 代码</li>
<li>eval 代码：eval()函数计算某个字符串，并执行其中的 js 代码，比如：<code>eval(&quot;alert(&#39;hello woeld&#39;)&quot;)</code></li>
</ul>
<p>当 js 引擎遇到这三种类型的代码时候，都是会进行一些准备工作，这些准备工作，专业的说法就叫执行上下文。</p>
<p>简单来说，执行上下文就是评估和执行 js 代码的环境的抽象概念。每当 js 代码在运行的时候，他都是在执行上下文运行。执行上下文可以理解为当前代码的执行环境，他会形成一个作用域。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">js代码的整个执行过程，分为两个阶段，代码编译阶段与代码执行阶段。编译阶段由编译器完成，将代码编译成可执行代码，这个阶段作用域规则会确定。执行阶段由引擎完成，主要任务是执行课执行代码，执行上下文在这个阶段创建</span><br></pre></td></tr></table></figure>

<p>1.2.1 那么 js 引擎在遇到可执行代码的时候，它究竟会做哪些准备工作呢</p>
<ul>
<li><p>全局执行上下文：创建一个全局的 window 对象（浏览器的情况下），并且设置 this 的值等于这个全局对象。一个程序只有一个全局执行上下文</p>
</li>
<li><p>函数执行上下文：每当一个函数被调用时，都会为该函数创建一个新的上下文，每个函数都有自己的执行上下文，不过是在函数被调用时调用时创建的，函数的上下文可以有人一个，每当一个新的执行上下文被创建，他会按定义的顺序执行一系列步骤</p>
<p>1.2.2 执行上下文栈</p>
</li>
</ul>
<p>在 js 程序中，必定会产生多个执行上下文，js 引擎会以栈的方式来处理它们，它就是执行上下文栈</p>
<h2 id="2-理解执行上下文"><a href="#2-理解执行上下文" class="headerlink" title="2.理解执行上下文"></a>2.理解执行上下文</h2><p>1.2.3 执行上下文的生命周期</p>
<p>创建阶段</p>
<ul>
<li>生成变量对象</li>
<li>建立作用域链</li>
<li>确定 this 指向</li>
</ul>
<p>执行阶段</p>
<ul>
<li>变量赋值</li>
<li>函数引用</li>
<li>执行其他代码</li>
</ul>
<h3 id="1-3-作用域链增强"><a href="#1-3-作用域链增强" class="headerlink" title="1.3 作用域链增强"></a>1.3 作用域链增强</h3><p>作用域链是什么？</p>
<p>包含了函数被创建的作用域中对象的集合就是 js 中的作用域链。作用域链决定了哪些数据能被函数访问。当一个函数创建后，他的作用域链会被创建此函数的作用域中可访问的数据对象填充</p>
<p>某些语句会导致在作用域前端临时添加一个上下文，这个上下文在代码执行后会被删除</p>
<p>Try/catch 语句中的 catch 块</p>
<p>with 语句</p>
<p>这两种情况下，都会在作用域链前添加一个变量对象。对 with 来说，会向作用域链前添加指定的对象；对 catch 语句而言，则会创建一个新的变量对象，这个变量对象会包含要抛出错误对象的声明</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">buildUrl</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> qs = <span class="string">&quot;? debug=true&quot;</span>;</span><br><span class="line">  <span class="keyword">with</span> (location) &#123;</span><br><span class="line">    <span class="keyword">let</span> url = href + qs;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> url;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// with语句将location对象作为上下文，因此location会被添加到作用域链前端。当with语句中的代码引用变量href时，实际上引用的事location.href，也就是自己的变量对象属性，在引用qs时，引用的则是定义在buildUrl（）中的那个变量，他定义在函数上下文的变量对象上，</span></span><br></pre></td></tr></table></figure>

<p>1.3.1 变量声明</p>
<p>es6 之后，js 的变量声明经历了翻天覆地的变化，不仅增加了 let 和 const 两个关键字，而且还让这两个关键字压倒性地超越 var 称为首选</p>
<ul>
<li>使用 var 的函数作用域声明</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">在使用<span class="keyword">var</span>声明变量时，变量会被自动添加到最接近的上下文。在函数中最接近的上下文就是函数的局部上下文。在<span class="keyword">with</span>语句中最接近的上下文也是函数上下文。如果变量未经声明就被初始化，那么它会自动被添加到全局上下文</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">num1,num2</span>)</span>&#123;</span><br><span class="line">  <span class="keyword">var</span> sum = sum1 + sum2;</span><br><span class="line">  <span class="keyword">return</span> sum;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> result = add(<span class="number">10</span>,<span class="number">20</span>)</span><br><span class="line"><span class="built_in">console</span>.log(sum) <span class="comment">// VM1526:1 Uncaught ReferenceError: sum is not defined</span></span><br><span class="line"><span class="comment">// add()是定义了一个局部变量sum，保存加法操作的结果。这个值作为函数的值返回，但变量sum在函数外部是访问不到的，如果省略上面例子中的关键字var,那么sum在ad（）被调用之后就可以变成可以访问的</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">num1,num2</span>)</span>&#123;</span><br><span class="line">  sum = sum1 + sum2</span><br><span class="line">  <span class="keyword">return</span> sum;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> result = add(<span class="number">10</span>,<span class="number">20</span>)</span><br><span class="line"><span class="built_in">console</span>.log(sum) <span class="comment">// 30</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这一次变量sum被用加法操作的结果初始化并没有使用var声明，在调用add()之后，sum被添加到全局上下文，在函数退出之后仍然存在</span></span><br><span class="line">tips:未经声明而初始化的变量是js常见错误，在严格模式会报错</span><br></pre></td></tr></table></figure>

<p>var 声明会被拿到函数或全局作用域的顶部，位于作用域中所有代码之前，这个现象叫做提升。提升让同一作用域的代码不必考虑变量是否已经声明就可以直接使用。可在实践中，提升也会导致合法却奇怪的现象，即在变量声明之前使用变量</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;jake&#x27;</span>;</span><br><span class="line">===</span><br><span class="line">name = <span class="string">&#x27;jke&#x27;</span></span><br><span class="line"><span class="keyword">var</span> name;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn1</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="keyword">var</span> name = <span class="string">&#x27;jake&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn2</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="keyword">var</span> name;</span><br><span class="line">  name = <span class="string">&#x27;jake&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过声明之前打印变量，可以验证变量会被提升。声明意味着会输出undefined而不是Reference Error</span></span><br></pre></td></tr></table></figure>

<ul>
<li>使用 let 的块级作用域声明</li>
</ul>
<p>与 var 类似，但它的作用域是块级的。块级作用域由最近的一堆花括号界定。简单说，if 块、while 块、function 块甚至是单独的块也是 let 声明变量的作用域</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> a;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(a); <span class="comment">// a 没有定义</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这不是对象字面量，而是一个独立的块，js解释器会根据其中内容识别出来</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> d;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(d); <span class="comment">// d没有定义</span></span><br></pre></td></tr></table></figure>

<p>与 var 另一个不同点是：重复的 var 会被忽略，而重复额 let 会抛出 SyntaxError</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a;</span><br><span class="line"><span class="keyword">var</span> a;</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">let</span> b;</span><br><span class="line">  <span class="keyword">let</span> b; <span class="comment">// error</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>let 的行为非常适合在循环中声明迭代变量。使用 var 声明的迭代变量会泄漏到循环外部</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;&#125;</span><br><span class="line"><span class="built_in">console</span>.log(i); <span class="comment">// 10</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">0</span>; i++) &#123;&#125;</span><br><span class="line"><span class="built_in">console</span>.log(i); <span class="comment">// ReferenceError</span></span><br></pre></td></tr></table></figure>

<p>严格来讲，let 在 js 运行的时候也会提升，但是由于暂时性死区的缘故，实际上不能再声明之前使用 let 变量</p>
<ul>
<li>const 的常量变量</li>
</ul>
<p>使用 const 声明的变量必须同时初始化未某个值。一经声明，在其生命周期的任何时候不能重新赋予新值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> a; <span class="comment">// syntaxError 常量声明时没有初始化</span></span><br><span class="line"><span class="keyword">const</span> b = <span class="number">3</span>;</span><br><span class="line"><span class="built_in">console</span>.log(b); <span class="comment">// 3</span></span><br><span class="line">b = <span class="number">4</span>; <span class="comment">// typeError</span></span><br></pre></td></tr></table></figure>

<p>Const 声明只应用到顶级原语或者对象。简单来说就是赋值为对象的 const 变量不能在被重新赋值为其他引用值，但对象的键不受控制</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> o1 = &#123;&#125;;</span><br><span class="line">o1 = &#123;&#125;; <span class="comment">// typeError</span></span><br><span class="line"><span class="keyword">const</span> o2 = &#123;&#125;;</span><br><span class="line">o2.name = <span class="string">&quot;jake&quot;</span>;</span><br></pre></td></tr></table></figure>

<p>如果想让整个对象都不能进行修改，可以使用 Object.freeze(),这样再给属性赋值时虽然不会报错，但会静默失败</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> o3 = <span class="built_in">Object</span>.freeze(&#123;&#125;);</span><br><span class="line">o3.name = <span class="string">&quot;jake&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(o3.name); <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure>

<ul>
<li>标识符查找</li>
</ul>
<p>当在特定上下文中为读取或写入而引用一个标识符时，必须通过搜素确定这个标识符表示什么。搜素开始与作用链前端，以给定的名称搜索对应的标识符。如果在局部上下文中找到该标识符，则搜索停止，变量确定。如果没有找到变量名，则继续沿作用域链搜索。这个过程一直持续至全局上下文的变量对象。如果仍然没有找到标识符，则其说明未声明</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> color = <span class="string">&quot;blue&quot;</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getColor</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> color;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(getColor()); <span class="comment">// blue</span></span><br><span class="line"><span class="comment">// 在这个例子中，调用函数getColor会引用变量color。为确定color的值会进行两步搜索，第一步，搜索getColor()变量对象，查找名为color的标识符，因为全局变量对象上有color的定义，所以搜索结束</span></span><br><span class="line"><span class="comment">// 如果引用局部变量会让搜索自动结束</span></span><br></pre></td></tr></table></figure>

<p>使用块级作用域声明并不会改变搜索流程，但可以给词法添加额外的层次</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> color = <span class="string">&#x27;blue&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getColor</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="keyword">let</span> color = <span class="string">&#x27;red&#x27;</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">let</span> color = <span class="string">&#x27;green&#x27;</span></span><br><span class="line">    retur color</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(getColor()) <span class="comment">// green</span></span><br><span class="line"><span class="comment">// getColor内部声明了一个名为color的局部变量。在调用这个函数的时候，变量会被声明。在执行到这个函数时，代码引用变量color.于是开始在局部上下文搜索这个标识符，结果找到了值为green的变量color。因为变量已经找到，搜索随即停止</span></span><br></pre></td></tr></table></figure>

<p>标识符查找不是没有代价，访问局部变量比访问全局变量要快，因为不用切换作用域</p>
<p><strong>补充</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">10</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(a)</span><br><span class="line">  <span class="keyword">var</span> a = <span class="number">10</span></span><br><span class="line">  <span class="built_in">console</span>.log(a)</span><br><span class="line">&#125;</span><br><span class="line"><span class="literal">undefined</span> <span class="number">10</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">	<span class="keyword">var</span> x = <span class="number">10</span></span><br><span class="line">  ++x</span><br><span class="line">  <span class="built_in">console</span>.log(x)</span><br><span class="line">&#125;</span><br><span class="line"><span class="literal">undefined</span> <span class="number">11</span></span><br></pre></td></tr></table></figure>

<h3 id="1-4-js-编译过程-VO-AO"><a href="#1-4-js-编译过程-VO-AO" class="headerlink" title="1.4 js 编译过程 VO AO"></a>1.4 js 编译过程 VO AO</h3><p>编译过程</p>
<ul>
<li>发现有代码 -&gt; 调用一个函数</li>
<li>在执行这个 function 之前，创建一个执行上下文(execution context)，也可以叫执行环境。</li>
<li>进入创建阶段（VO 创建）<ul>
<li>初始化作用域链(scope chain)</li>
<li>创建变量函数(variable object / VO)</li>
<li>创建参数对象（arguments object，传进来的参数），检查上下文，初始化其名字和值，以及建立引用对象的拷贝</li>
<li>扫描上下文中的函数声明</li>
<li>为每一个扫描到的函数声明在 Vo 中创建一个属性，命名为函数的名字，指向了存储空间中的对应函数</li>
<li>如果函数名称已经存在了，这个引用指针将被重写为新的这一个</li>
<li>扫描上下文中的变量声明</li>
<li>为每一个扫描到的变量在 VO 中创建一个属性，命名为变量的名字，初始值为 undefined</li>
<li>如果变量名在内存中已经存在了，就跳过</li>
<li>决定上下文中 this 的指向</li>
</ul>
</li>
<li>执行阶段<ul>
<li>执行/解释上下文中的 function，为变量赋值</li>
<li>代码按行执行</li>
</ul>
</li>
</ul>
<p>他们相应的概念</p>
<p>Scope:变量/函数起作用的区域</p>
<p>Scope chain:保证对执行环境有权访问的所有变量和函数的有序访问。相当于 VO+[scope]我们可以将作用域定义为一套规则，用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符名称进行变量的查找，作用域链是这套规则的具体实现</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">exection context = &#123;VO,<span class="built_in">this</span>,[scope]&#125;</span><br><span class="line"><span class="built_in">this</span>:函数/方法的拥有者</span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/200910488">https://zhuanlan.zhihu.com/p/200910488</a></p>
<h2 id="3-理解垃圾回收"><a href="#3-理解垃圾回收" class="headerlink" title="3.理解垃圾回收"></a>3.理解垃圾回收</h2><p>js 是使用垃圾回收的语言，也就是说执行环境负责在代码执行是管理内存。跟踪内存使用对开发来说是个大负担。js 通过自动内存管理实现内存分配和闲置资源回收。基本思路就是：确定哪个变量不在使用，然后释放它占用的内存。函数中的局部变量会在函数执行时存在，此时，栈内存分配空间以保存相应的值。在浏览器发展历史上，用到过两种主要的标记策略：标记清理和引用计数。</p>
<h3 id="3-1-1-标记清理"><a href="#3-1-1-标记清理" class="headerlink" title="3.1.1 标记清理"></a>3.1.1 标记清理</h3><p>js 最常用的垃圾回收策略</p>
<p>当变量进入上下文，比如在函数内部声明一个变量时，这个变量会被加上存在于上下文的标记。而在上下文中的变量，逻辑上讲，永远不应该释放它们的内存，因为只要有上下文中的代码在运行，就可能用到它们。</p>
<p>给变量添加标记的方式有很多种。</p>
<h3 id="3-1-2-引用计数"><a href="#3-1-2-引用计数" class="headerlink" title="3.1.2 引用计数"></a>3.1.2 引用计数</h3><p>思路就是对每个值都记录它被引用的次数。声明变量并给它赋一个引用值时，这个值的引用数为 1.如果同一个值又被赋给另一个变量，那么引用数加 1.如果保存对该值引用的变量被其他值给覆盖了，那么引用数减 1</p>
<p>问题：循环引用</p>
<p>对象 A 包含一个指向对象 B 的指针，而对象 B 中也包含一个指向 A 的指针</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">obj</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> objA = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">  <span class="keyword">var</span> objB = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">  objA.propertyA = objBl;</span><br><span class="line">  objB.property = objA;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>解决</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">objA.propertyA = <span class="literal">null</span>;</span><br><span class="line">objB.property = <span class="literal">null</span>;</span><br></pre></td></tr></table></figure>

<h3 id="3-1-3-性能"><a href="#3-1-3-性能" class="headerlink" title="3.1.3 性能"></a>3.1.3 性能</h3><p>垃圾回收程序会周期性运行，如果内存中分配了很多变量，则可能造成性能损失，因此垃圾回收时间的调度很重要。垃圾回收会明显拖慢渲染的速度和帧速率。开发者不知道什么时候运行时会收集垃圾，因此最好的办法是在写代码时要做到，无论什么时候开始收集垃圾，都能让它尽快结束。</p>
<h3 id="3-1-4-内存管理"><a href="#3-1-4-内存管理" class="headerlink" title="3.1.4 内存管理"></a>3.1.4 内存管理</h3><p>在使用垃圾回收的编程环境中，开发者无需关心内存管理。将内存占用量保持在一个较小的值可以让页面性能更好。优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createPerson</span>(<span class="params">name</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> localPerson = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">  localPerson.name = name;</span><br><span class="line">  <span class="keyword">return</span> localPerson;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> globalPerson = createPerson(<span class="string">&quot;nick&quot;</span>);</span><br><span class="line">globalPerosn = <span class="literal">null</span>;</span><br></pre></td></tr></table></figure>

<p>在上面代码中，变量 globalPerson 保存着 createPerson 的调用值。在 createPerson 内部，localPerson 创建了一个对象并给他添加一个 name 属性。localPerson 在 createPerson()执行完成超出上下文后会自动解除引用，不需要显示处理。</p>
<ul>
<li>通过 const 和 let 声明提升性能</li>
</ul>
<p>es6 增加这两个关键字不仅有助于改善代码风格，而且同样有助于改进垃圾回收的过程。因为 const 和 let 都以块为作用域，所以相比于使用 var，使用这两个新关键字可能会更早地让垃圾回收程序介入，今早回收应该回收的内存。</p>
<ul>
<li>隐藏类和删除操作</li>
</ul>
<p>根据 js 所在的运行环境，运行期间 v8 会创建的对象与隐藏类关联起来，跟踪他们的属性特征。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Article</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.title = <span class="string">&quot;title&quot;</span>;</span><br><span class="line">  <span class="keyword">let</span> a1 = <span class="keyword">new</span> Article();</span><br><span class="line">  <span class="keyword">let</span> a2 = <span class="keyword">new</span> Article();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//v8会在后台配置，让这两个类实例共享相同的隐藏类，因为这两个实例共享同一个构造函数和原型。</span></span><br></pre></td></tr></table></figure>

<ul>
<li>内存泄漏</li>
</ul>
<p>在内存有限的设备上，或者在函数会被调用多次的情况下，内存泄漏是大问题。</p>
<p>意外声明全局变量是最常见但也是最容易修复的。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">setName</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  name = <span class="string">&quot;jake&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// == window.name 只要window本身不被清理就不会消失</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定时器也会导致内存泄漏</span></span><br><span class="line"><span class="keyword">let</span> name = <span class="string">&quot;jake&quot;</span>;</span><br><span class="line"><span class="built_in">setInterval</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(name);</span><br><span class="line">&#125;, <span class="number">100</span>);</span><br><span class="line"><span class="comment">//只要定时器一直运行，回调函数中引用的name就会一直占用内存</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// js闭包也很容易造成泄漏</span></span><br><span class="line"><span class="keyword">let</span> outer = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> name = <span class="string">&quot;jake&quot;</span>;</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> name;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// 以上代码执行后创建一个内部闭包，只要返回的函数存在就不能清理name，因为闭包一直在引用着它</span></span><br></pre></td></tr></table></figure>

<ul>
<li>静态分配与对象池</li>
</ul>
<p>为了提升 js 性能，最后要考虑的就是一步步压榨浏览器。一个关键问题就是如何减少浏览器回收的次数。开发者无法直接控制什么时候开始收集垃圾，但可以进阶控制触发垃圾回收的条件。</p>
<p><strong>例</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = &#123; <span class="attr">n</span>: <span class="number">1</span> &#125;;</span><br><span class="line"><span class="keyword">let</span> b = a;</span><br><span class="line">a.x = a = &#123; <span class="attr">n</span>: <span class="number">2</span> &#125;;</span><br><span class="line"><span class="built_in">console</span>.log(a.x);</span><br><span class="line"><span class="built_in">console</span>.log(b);</span><br></pre></td></tr></table></figure>

<p>整个过程的对象只有两个{n:1}和{n:2}下面分别称为 A 对象和 B 对象 然后他们之间相互赋值和增加属性，记住仅有两个引用地址</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span>首先将&#123;<span class="attr">n</span>:<span class="number">1</span>&#125;对象赋值给a变量，在将a赋值给b，这是一层浅拷贝的过程，所以a和b变量都指向同一个对象&#123;<span class="attr">n</span>:<span class="number">1</span>&#125;</span><br><span class="line"><span class="number">2.</span>由于点运算符优先于赋值符所以先在&#123;n：<span class="number">1</span>&#125;对象中创建了一个x属性 &#123;<span class="attr">n</span>:<span class="number">1</span>， x：（暂时无值）&#125; 这个过程 因为运算符优先级的原因 赋值符号还未执行的时候就已经完成了</span><br><span class="line"><span class="number">3.</span>再然后执行 a = &#123;<span class="attr">n</span>: <span class="number">2</span>&#125; 此时a的引用地址发生了改变 从对象&#123;<span class="attr">n</span>:<span class="number">1</span>&#125;指向了&#123;<span class="attr">n</span>:<span class="number">2</span>&#125;</span><br><span class="line"><span class="number">4.</span>a.x此时指向的是 &#123;<span class="attr">n</span>:<span class="number">1</span>， x：（暂时无值）&#125;对象 然后将&#123;n：<span class="number">2</span>&#125; 赋值给了a.x属性 此时A对象&#123;<span class="attr">n</span>:<span class="number">1</span>， x：&#123;n：<span class="number">2</span>&#125;&#125;</span><br><span class="line"><span class="number">5.</span>此时的a.x属性的父级对象a的初始引用地址是A对象 而A对象赋值给了b变量 所以你能在b.x中得到对象&#123;n：<span class="number">2</span></span><br><span class="line"><span class="number">6.</span>原对象地址因无人引用他 被垃圾回收机制回收了 对象被赋值了B对象&#123;n：<span class="number">2</span>&#125; 所以原有的a.x为<span class="literal">undefined</span></span><br></pre></td></tr></table></figure>

<p>.运算优先于= 赋值运算，因此此处赋值可理解为</p>
<ul>
<li>声明 a 对象中的 x 属性，用于赋值，此时 b 指向 a，同时拥有未赋值的 x 属性</li>
<li>对 a 对象赋值，此时变量名 a 改变指向到对象{n:2}</li>
<li>对于步骤 1 中的 x 属性，也即是指向对象的 x 属性，也即 b 指向对象的 x 属性赋值</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a =&gt; &#123;<span class="attr">n</span>:<span class="number">2</span>&#125;</span><br><span class="line">b =&gt; &#123;<span class="attr">n</span>:<span class="number">1</span>,<span class="attr">x</span>:&#123;<span class="attr">n</span>:<span class="number">2</span>&#125;&#125;</span><br></pre></td></tr></table></figure>

<p>另一种说法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span>多次赋值与顺序无关，是同时进行赋值的</span><br><span class="line"><span class="number">2.</span>每个节点的变量最终赋值的值取决去最后一个等号的右边值</span><br><span class="line"><span class="number">3.</span>如果赋值是引用类型，则最终指向的是同一个对象</span><br></pre></td></tr></table></figure>

<p>a.x 引用的是堆内存里面的属性变量，在解析时会直接对这个地址的变量进行操作，而 a=访问变量栈内存里面这个变量名，所以进行赋值操作并不会影响前者，因为解析这个语句时一次性全部读取在进行赋值，而不是分段读取赋值的。所以就解释了与顺序无关，所有的属性都将会被赋值到最右的值。</p>
<p>小结：</p>
<p>js 变量可以保存两种类型的值：原始值和引用值。原始值可能是以下 6 种原始数据类型之一：undefined、null、Boolean、Number、String 和 Symbol.原始值和引用值有以下特点</p>
<ul>
<li>原始值大小固定，因此保存在栈内存上，它由系统自动释放</li>
<li>从一个变量到另一个变量复制原始值会创建该值的第二个副本</li>
<li>引用值是对象，存储在堆内存上</li>
<li>包含引用值的变量实际上只包含指向相应对象的一个指针，而不是对象本身</li>
<li>从一个变量到另一个变量复制引用值只会复制指针，因此结果是两个变量都指向同一个对象</li>
<li>typeof 操作符可以确定值的原始类型，而 instanceof 操作符用于确保值的引用类型</li>
</ul>
<p>任何变量都存在于某个执行上下文中（也称作用域）。这个上下文（作用域）决定了变量的声明周期，以及它们可以访问代码的哪些部分。执行上下文可以总结如下</p>
<ul>
<li>执行上下文分为全局上下文呢、函数上下文和块级上下文</li>
<li>代码执行流每进入一个新的上下文，都会创建一个作用域链，用于搜索变量和函数</li>
<li>函数或块的局部上下文不仅可以访问自己作用域内的变量，而且也可以访问任何包含上下文乃至全局上下文中的变量。</li>
<li>全局上下文只能访问全局上下文的变量和函数，不能直接访问局部上下文种的任何数据。</li>
<li>变量的执行上下文用于确定什么时候释放内存</li>
</ul>
<p>js 是使用垃圾回收的编程语言，开发者不需要操心内存分配和回收。</p>
<ul>
<li>离开作用域的值会被自动标记为可回收，然后在垃圾回收期间被删除</li>
<li>主流的垃圾回收算法是标记清理，即先给当前不适用的值加上标记，在回来回收它们的内存</li>
<li>引用计数是另一种垃圾回收策略，需要记录值被引用了多少次。js 引擎不在使用这种算法，但某些版本的 ie 仍会受到影响。</li>
<li>引用计数在代码中存在循环引用时会出现问题</li>
<li>解除变量的引用不仅可以消除循环引用，而且对垃圾回收也有帮助。为促进内存回收，全局对象、全局对象的属性和循环引用都应该在不需要时解除引用</li>
</ul>

      
    </div>

    
    
    
      <div>
          
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://skycoin.gitee.io/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4083356047,3551369852&fm=26&gp=0.jpg">
      <meta itemprop="name" content="若说">
      <meta itemprop="description" content="立志完成前端知识体系的架构">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="若水的前端博客">
    </span>
      <header class="post-header">
      
        <i class="fa fa-thumb-tack"></i>
        <font color=7D26CD>置顶</font>
      
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/" class="post-title-link" itemprop="url">Javascript基础（四）：javascript基本引用类型</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-27 10:14:52" itemprop="dateCreated datePublished" datetime="2021-02-27T10:14:52+08:00">2021-02-27</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-15 09:25:56" itemprop="dateModified" datetime="2021-04-15T09:25:56+08:00">2021-04-15</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/codeblog/categories/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">前端框架</span></a>
                </span>
            </span>

          
            <span id="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/" class="post-meta-item leancloud_visitors" data-flag-title="Javascript基础（四）：javascript基本引用类型" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/codeblog/2021/02/27/%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>[toc]</p>
<h2 id="1-理解对象"><a href="#1-理解对象" class="headerlink" title="1.理解对象"></a>1.理解对象</h2><p>引用值（或者对象）是某个特定引用类型的实例。在 es 中，引用类型是把数据和功能组织到一起的结构，经常被人错误的称为类。虽然从技术上来讲 js 是一门面向对象语言，但 es 却少传统的面向对象编程所具备的某些基本结构，包括类和接口。引用类型有时候也被称为对象定义，因为它们描述了自己的对象应有的属性和方法</p>
<p>对象被认为是某个特定引用类型的实例。新对象通过使用 new 操作符后跟一个构造函数来创建，构造函数就是用来创建新对象的函数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> now = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br></pre></td></tr></table></figure>

<p>这行代码创建了引用类型 Date 的一个新实例，并将它保存在变量 now 中，Date()在这里是构造函数，它负责创建一个只有默认属性和方法的简单对象，es 提供了很多像 Date 这样的原生引用类。</p>
<p>1.1.1 Date</p>
<p>Date 类型将日期保存为自协调世界时(UTC,Universal Time coordinated)时间 1970 年 1 月 1 日零点。</p>
<p>要创建日期对象，就要使用 new 操作符来调用 Date 构造函数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> now = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line"><span class="comment">// 必须要传毫秒数</span></span><br><span class="line"><span class="built_in">Date</span>.parse()方法接收一个表示日期字符串参数</span><br><span class="line"><span class="built_in">Date</span>.parse()</span><br><span class="line"><span class="built_in">Date</span>.parse(<span class="string">&quot;3-7-2013&quot;</span>)</span><br><span class="line"><span class="built_in">Date</span>.parse(<span class="string">&quot;03-07-2013&quot;</span>) <span class="comment">//返回时间戳</span></span><br></pre></td></tr></table></figure>

<p>要创建一个“2019 年 5 月 23 日”日期对象</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> someDate = <span class="keyword">new</span> <span class="built_in">Date</span>(<span class="built_in">Date</span>.parse(<span class="string">&quot;May 23,2019&quot;</span>));</span><br><span class="line">===</span><br><span class="line"><span class="keyword">let</span> someDate = <span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">&quot;May 23,2019&quot;</span>)</span><br></pre></td></tr></table></figure>

<h3 id="1-1-1-继承的方法"><a href="#1-1-1-继承的方法" class="headerlink" title="1.1.1 继承的方法"></a>1.1.1 继承的方法</h3><p>与其他类型一样，Date 类型重写了 toLocaleString()、toString（）和 valueOf()方法，但与其他类型不同，重写后这样方法的返回值不一样。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">getTime(); <span class="comment">// 返回日期的毫秒表示；与valueof相同</span></span><br></pre></td></tr></table></figure>

<h3 id="1-1-2-RegExp"><a href="#1-1-2-RegExp" class="headerlink" title="1.1.2 RegExp"></a>1.1.2 RegExp</h3><p>es 通过 RegExp 类型支持正则表达式。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> expression = <span class="regexp">/pattern/</span>afgls;</span><br></pre></td></tr></table></figure>

<p>每个正则表达式可以带零个或多个 flags（标记），用于控制正则表达式的行为。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">g:全局模式，表示查找字符串的全部内容，而不是找到第一个匹配的内容</span><br><span class="line">i:不区分大小写</span><br><span class="line">m：多行模式，表示查找到一行文本末尾会继续查找</span><br><span class="line">y：粘附模式</span><br><span class="line">u:unicode模式</span><br><span class="line">s:匹配任何字符</span><br><span class="line"></span><br><span class="line"><span class="comment">//匹配字符串中的所有 at</span></span><br><span class="line"><span class="keyword">let</span> pattern1 = <span class="regexp">/at/g</span>;</span><br></pre></td></tr></table></figure>

<h3 id="1-2-原始值包装类型"><a href="#1-2-原始值包装类型" class="headerlink" title="1.2 原始值包装类型"></a>1.2 原始值包装类型</h3><p>为了方便操作原始值，es 提供了 3 中特殊的引用类型:Boolean、Number 和 string.每当使用到某个原始值的方法或属性时，后台都会创建一个相应原始包装类型的对象，从而暴露出操作原始值的各种方法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> s1 = <span class="string">&quot;some&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> s2 = s1.substring(<span class="number">2</span>);</span><br><span class="line"><span class="comment">// s1是一个包含字符串的变量，它是一个原始值。第二行紧接着在s1上调用了substring方法，并把结果</span></span><br><span class="line"><span class="comment">// 保存在s2中，原始值本身不是对象，因此逻辑上不应该有方法。而实际上后台进行了很多处理，从而实现上述操作。具体来说当第二行访问s1时，是以已读模式访问的，也就是要从内存中读取变量保存的值</span></span><br></pre></td></tr></table></figure>

<p>在以读模式访问访问字符串的任何时候，后台都会执行这三步</p>
<ul>
<li>创建一个 String 类型的实例</li>
<li>调用实例上的特定方法</li>
<li>销毁实例</li>
</ul>
<p>可以把这 3 步想象成执行了下面 3 行 es 代码</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> s1 = <span class="keyword">new</span> <span class="built_in">String</span>(<span class="string">&quot;some text&quot;</span>);</span><br><span class="line"><span class="keyword">let</span> s2 = s1.substring(<span class="number">2</span>);</span><br><span class="line">s1 = <span class="literal">null</span>;</span><br></pre></td></tr></table></figure>

<p>这种行为可以让原始值拥有对象的行为。</p>
<p>引用类型与原始值包装类型的主要区别在于对象的生命周期。在通过 new 实例化引用类型后，得到的实例会在离开作用域时被销毁，而在自动创建的原始值包装对象则只存在于访问它的那行代码的执行期间。这意味着不能在运行时给原始值添加属性</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> s1 = <span class="string">&quot;some&quot;</span>;</span><br><span class="line">s1.color = <span class="string">&quot;red&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(s1.color); <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure>

<p>解读：在非严格模式下，当我们尝试给原始值赋值时，其实是生成了一个原始值包装类型实例，也是给这个新生成的实例进行赋值，但在赋值结束之后，这个实例就会被销毁了。实际上并没有把值赋值给我们想要的目标变量上，当我们下次再读取这个属性的时候，其实是又创建了一个原始值包装类型实例，显然这个实例不是和之前的实例一致，所以自然读取不到属性值</p>
<p>可以显式的使用 Boolean、Number 和 String 构造函数创建原始值包装对象。不过应该在确实必要在这样做，否则会让开发产生疑惑，分不清是原始值还是引用值。在原始值包装类型的实例上调用 typeOf 会返回 object，所有原始值包装对象都会转换为布尔值 true</p>
<p>另外，Object 构造函数作为一个工厂方法，能够根据传入值的类型返回相应的原始包装类型实例</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = <span class="keyword">new</span> <span class="built_in">Object</span>(<span class="string">&quot;some&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(obj <span class="keyword">instanceof</span> string); <span class="comment">// true</span></span><br><span class="line"><span class="comment">// 如果传递给object是字符串，则会创建一个String实例</span></span><br><span class="line"><span class="comment">// 传递数值，则会创建Number实例</span></span><br><span class="line"><span class="comment">// 传递布尔值，则会得到Boolean的实例</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-1-Boolean"><a href="#1-2-1-Boolean" class="headerlink" title="1.2.1 Boolean"></a>1.2.1 Boolean</h4><p>Boolean 对应布尔值的引用类型。要创建一个布尔对象，就是用 Boolean 构造函数传入 true 或 false</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> booleanObject = <span class="keyword">new</span> <span class="built_in">Boolean</span>(<span class="literal">true</span>);</span><br></pre></td></tr></table></figure>

<p>Boolean 的实例会重写 valueOf 方法，返回一个 true 或 false。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> falseObject = <span class="keyword">new</span> <span class="built_in">Boolean</span>(<span class="literal">false</span>);</span><br><span class="line"><span class="keyword">let</span> res = falseObject &amp;&amp; <span class="literal">true</span>;</span><br><span class="line"><span class="built_in">console</span>.log(res); <span class="comment">// true</span></span><br><span class="line"><span class="keyword">let</span> falseValue = <span class="literal">false</span>;</span><br><span class="line">res = falseValue &amp;&amp; <span class="literal">true</span>;</span><br><span class="line"><span class="built_in">console</span>.log(res); <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typeof</span> falseObject; <span class="comment">//object</span></span><br><span class="line"><span class="keyword">typeof</span> falseValue; <span class="comment">// boolean</span></span><br><span class="line">falseObject <span class="keyword">instanceof</span> <span class="built_in">Boolean</span>; <span class="comment">// true</span></span><br><span class="line">falseValue <span class="keyword">instanceof</span> <span class="built_in">Boolean</span>; <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<p>注意：所有对象在布尔表达式中都会自动转换为 true,因此 falseObject 在这个表达式里是加上表示一个 true 值。</p>
<p>除此之外，原始值和引用值（Boolean 对象）还有几个区别</p>
<p>typeof 操作符对原始值返回 boolean，但对引用值返回 object</p>
<h4 id="1-2-2-Number"><a href="#1-2-2-Number" class="headerlink" title="1.2.2 Number"></a>1.2.2 Number</h4><p>Number 是对应数值的引用类型。要创建一个 Number 对象，就要使用 Number 构造函数并传入一个数值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> numberObject = <span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">10</span>);</span><br></pre></td></tr></table></figure>

<p>与 Boolean 一样，Number 类型重写了 valueOf()、toLocalString()和 toString()方法。valueOf()方法返回 Number 对象表示的原始数值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">10</span>;</span><br><span class="line">num.toString(); <span class="comment">// &quot;10&quot;</span></span><br><span class="line">num.toString(<span class="number">2</span>); <span class="comment">// &quot;1010&quot;</span></span><br><span class="line">num.toString(<span class="number">8</span>); <span class="comment">// &quot;12&quot;</span></span><br><span class="line">num.toString(<span class="number">10</span>); <span class="comment">// 10</span></span><br><span class="line">num.toString(<span class="number">16</span>); <span class="comment">// a</span></span><br></pre></td></tr></table></figure>

<p>toFixed()方法返回包含指定小数点的数值字符串.如果数值本身的小数位超过参数指定的位数，则四舍五入到最接近的小数位</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">10.005</span>;</span><br><span class="line">num.toFixed(<span class="number">2</span>); <span class="comment">// &quot;10.01&quot;</span></span><br><span class="line"><span class="comment">// 可以用来处理货币</span></span><br></pre></td></tr></table></figure>

<p>toExponential()返回科学计数法表示数值字符串</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">10</span>;</span><br><span class="line">num.toExponential(<span class="number">1</span>); <span class="comment">//&quot;1.0e+1&quot;  科学计数法</span></span><br></pre></td></tr></table></figure>

<p>toPrecision 方法会根据情况返回最合理的输出结果，可能是固定长度，也可能是科学计数法形式。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> num = <span class="number">99</span>;</span><br><span class="line">num.toPrecision(<span class="number">1</span>); <span class="comment">// &quot;1e+2&quot;</span></span><br><span class="line">num.toPrecision(<span class="number">2</span>); <span class="comment">// &quot;99&quot;</span></span><br><span class="line">num.toPrecision(<span class="number">3</span>); <span class="comment">// &quot;99.0&quot;</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-3-String"><a href="#1-2-3-String" class="headerlink" title="1.2.3 String"></a>1.2.3 String</h4><p>对应字符串的引用类型，String 对象的方法可以在所有字符串原始值上调用。3 个继承的方法 valueOf()、toLocaleString()和 toString()都返回对象的原始字符串</p>
<p>每个 string 对象都有一个 length 属性，表示字符串中字符串字符的数量</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> stringValue = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line">stringValue.length; <span class="comment">// 11</span></span><br></pre></td></tr></table></figure>

<p>string 类型提供了很多方法解析和操作字符串</p>
<ul>
<li>js 字符</li>
</ul>
<p>js 字符串由 16 位码元组成。对于数字符来说，每 16 位码元对应一个字符，换句话来说字符串的 length 属性表示字符串包含多少个码元</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> message = <span class="string">&quot;abcd&quot;</span>;</span><br><span class="line">message.length; <span class="comment">// 5</span></span><br></pre></td></tr></table></figure>

<p>另外 charAt()方法返回给定索引位置的字符，由传给方法的整数参数指定。</p>
<p>字符串的操作方法</p>
<ul>
<li>Concat()</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> res = <span class="string">&quot;aaa&quot;</span>.concat(<span class="string">&quot;bbb&quot;</span>);</span><br></pre></td></tr></table></figure>

<ul>
<li>es 提供了 3 个从字符串中提取字符串的方法: slice()、substr()、substring()</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&#x27;hello world&#x27;</span></span><br><span class="line">str.slice(<span class="number">3</span>) <span class="comment">// loworld</span></span><br><span class="line">str.substring(<span class="number">3</span>) <span class="comment">//</span></span><br><span class="line">str.substr(<span class="number">3</span>) <span class="comment">//</span></span><br><span class="line"></span><br><span class="line">str.slice(<span class="number">3</span>,<span class="number">7</span>) <span class="comment">// lo w</span></span><br><span class="line">str.substring(<span class="number">3</span>,<span class="number">7</span>) <span class="comment">// lo w</span></span><br><span class="line">str.substr(<span class="number">3</span>,<span class="number">7</span>) <span class="comment">// lo worl</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 当某个值是负值的时,slice()方法将所有负值参数都当成字符串长度加上负参数值</span></span><br><span class="line"><span class="comment">// substr()方法将第一个负参数值当成字符串长度加上该值，将第二个负参数值转换为0</span></span><br><span class="line"><span class="comment">//substring()将所有负参数值都转换为0</span></span><br><span class="line"><span class="keyword">let</span> str = <span class="string">&#x27;hello world&#x27;</span></span><br><span class="line"></span><br><span class="line">str.slice(-<span class="number">3</span>) <span class="string">&#x27;rld&#x27;</span></span><br><span class="line">str.substring(-<span class="number">3</span>) <span class="string">&#x27;hello world&#x27;</span></span><br><span class="line">str.substr(-<span class="number">3</span>) <span class="string">&#x27;rld&#x27;</span></span><br><span class="line">str.slice(<span class="number">3</span>,-<span class="number">4</span>) <span class="string">&#x27;low&#x27;</span></span><br><span class="line">str.substring(<span class="number">3</span>,-<span class="number">4</span>) <span class="string">&#x27;hel&#x27;</span></span><br><span class="line">str.substr(<span class="number">3</span>,-<span class="number">4</span>)  <span class="string">&#x27;&#x27;</span></span><br></pre></td></tr></table></figure>

<p>Slice 和 subStr 和 subString 区别</p>
<p>相同点</p>
<ul>
<li>都不会改变原始字符串</li>
<li>第一个参数都是指定字符串开始的位置</li>
<li>第二个参数不传则将字符串的尾部作为结束位置</li>
</ul>
<p>不同点</p>
<ul>
<li><p>Slice():第一个参数指定字符串的开始位置，第二个参数指定字符串的结束位置</p>
</li>
<li><p>Substring()会将小的参数作为开始位置，大的位置作为结束位置</p>
</li>
<li><p>Substr（）：第一个参数指定字符串开始的位置，第二个参数要返回的字符个数</p>
</li>
<li><p>Substring（）：参数为负值时，会将所有的负值参数转换成 0</p>
</li>
<li><p>substr 方法将负的第一个参数加上字符传的长度得到开始位置，将负的第二个参数转换 0</p>
</li>
<li><p>字符串位置方法</p>
</li>
</ul>
<p>有两个方法用于在字符串中定位子字符串:indexOf()和 lastIndexOf()。这两个方法从字符串搜索传入的字符串，并返回位置。</p>
<p>区别在于：indexOf()的方法从字符串开头开始查找字符串，而 lastIndexOf（）方法从字符串末尾开始查找字符串</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line">str.indexOf(<span class="string">&quot;o&quot;</span>); <span class="comment">// 4</span></span><br><span class="line">str.lastIndexOf(<span class="string">&quot;o&quot;</span>); <span class="comment">// 7</span></span><br></pre></td></tr></table></figure>

<p>这两个方法都可以接受可选的第二个参数，表示开始搜索的位置。这意味着，indexOf（）会从这个参数指定的位置开始像字符串末尾搜索，忽略该位置之前的字符，lastIndexOf()则会从这个参数指定的位置开始向字符串开头搜索。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line">str.indexOf(<span class="string">&quot;o&quot;</span>, <span class="number">6</span>); <span class="comment">// 7</span></span><br><span class="line">str.lastIndexOf(<span class="string">&quot;o&quot;</span>, <span class="number">6</span>); <span class="comment">//4</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 进行搜索的时候可以使用</span></span><br><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;xxxxxx...&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> pos = str.indexOf(<span class="string">&quot;x&quot;</span>);</span><br><span class="line"><span class="keyword">let</span> a = [];</span><br><span class="line"><span class="keyword">while</span> (pos &gt; -<span class="number">1</span>) &#123;</span><br><span class="line">  a.push(pos);</span><br><span class="line">  pos = str.indexOf(<span class="string">&quot;x&quot;</span>, pos + <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>字符串包含方法</li>
</ul>
<p>es 增加 3 个用于判断字符串中包含另一个字符串的方法：startWith()、endsWith()、includes()</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> msg = <span class="string">&quot;foobarbaz&quot;</span>;</span><br><span class="line">msg.startWith(<span class="string">&quot;foo&quot;</span>); <span class="comment">// true</span></span><br><span class="line">msg.startWith(<span class="string">&quot;bar&quot;</span>); <span class="comment">// false</span></span><br><span class="line">msg.endsWith(<span class="string">&quot;baz&quot;</span>); <span class="comment">// true</span></span><br><span class="line">msg.includes(<span class="string">&quot;bar&quot;</span>); <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 第二个参数表示开始搜索的位置</span></span><br><span class="line">msg.startsWith(<span class="string">&quot;foo&quot;</span>, <span class="number">1</span>); <span class="comment">//false</span></span><br><span class="line">msg.endsWith(<span class="string">&quot;bar&quot;</span>, <span class="number">6</span>); <span class="comment">//从后往前进行数</span></span><br></pre></td></tr></table></figure>

<ul>
<li>Trim()方法</li>
</ul>
<p>这个方法会创建一个副本，删除前后所有的空格符，在返回结果</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;    heloo woeld&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> str1 = str.trim();</span><br><span class="line"><span class="comment">// 	由于trim()返回的是字符串的副本，因此原始字符串不受影响，因此原始字符串不受影响</span></span><br></pre></td></tr></table></figure>

<ul>
<li>Repeat()方法</li>
</ul>
<p>es 在所有字符串上都提供了 repeat()方法。这个方法接受一个整数参数，表示要将字符串赋值多少次，然后拼接所有副本的结果</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;na. &quot;</span>;</span><br><span class="line">str.repeat(<span class="number">3</span>);</span><br></pre></td></tr></table></figure>

<ul>
<li>padStart 和 padEnd()方法</li>
</ul>
<p>padStart()和 padEnd()方法会复制字符串，，如果小于指定长度，则在一边填充字符</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;foo&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> b = str.padStart(<span class="number">6</span>);</span><br><span class="line">b.length; <span class="comment">// 6</span></span><br><span class="line"></span><br><span class="line">b.padEnd(<span class="number">9</span>, <span class="string">&quot;.&quot;</span>);</span><br><span class="line">(<span class="string">&quot;   aaa...&quot;</span>);</span><br></pre></td></tr></table></figure>

<ul>
<li>字符串的迭代和解构</li>
</ul>
<p>字符串的原型上暴露了一个@@iterator 方法，表示可以迭代字符串的每个字符。可以像下面这样手动使用迭代器</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> msg = <span class="string">&quot;abc&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> strIterator = msg[<span class="built_in">Symbol</span>.iterator]();</span><br><span class="line">strIterator.next(); <span class="comment">// &#123;value:&#x27;a&#x27;,done:false&#125;</span></span><br><span class="line">strIterator.next(); <span class="comment">// &#123;value:&#x27;b&#x27;,done:false&#125;</span></span><br><span class="line">strIterator.next(); <span class="comment">//&#123;value:&#x27;c&#x27;,done:false&#125;</span></span><br><span class="line">strIterator.next(); <span class="comment">//&#123;value:undefined,done:false&#125;</span></span><br></pre></td></tr></table></figure>

<p>在 for..of..循环中可以通过这个迭代器按序访问每个字符</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> c <span class="keyword">of</span> <span class="string">&quot;abcde&quot;</span>) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(c);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>有了这个迭代器之后，字符串就可以通过解构操作符来解构了，比如，可以方便的把字符串分割为字符数组</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> msg = <span class="string">&#x27;abcd&#x27;</span></span><br><span class="line">[...msg] <span class="comment">// [&#x27;a&#x27;,&#x27;b&#x27;,&#x27;c&#x27;,&#x27;d&#x27;]</span></span><br></pre></td></tr></table></figure>

<ul>
<li>字符串大小写转换</li>
</ul>
<p>下一组方法涉及大小写转换，包括四个方法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">toLowerCase();</span><br><span class="line">toLocaleLowerCase();</span><br><span class="line">toUpperCase();</span><br><span class="line">toLocaleUpperCase();</span><br><span class="line">toLowerCase();</span><br><span class="line">toUpperCase();</span><br></pre></td></tr></table></figure>

<ul>
<li>split</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colorText = <span class="string">&quot;red,green,blue,yellow&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> color1 = colorText.split(<span class="string">&quot;,&quot;</span>);</span><br><span class="line"><span class="keyword">let</span> color2 = colorText.split(<span class="string">&quot;,&quot;</span>, <span class="number">2</span>);</span><br></pre></td></tr></table></figure>

<ul>
<li>localCompare（）方法</li>
</ul>
<p>如果按照字母表顺序，字符串应该排在字符串参数前头，则返回负值</p>
<p>如果字符串与字符串参数相等，则返回 0</p>
<p>如果按照字母表顺序，字符串应该排在字符串参数的后头，则返回正值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> str = <span class="string">&quot;yellow&quot;</span>;</span><br><span class="line">str.localeCompare(<span class="string">&quot;brick&quot;</span>); <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h3 id="1-3-单例内置对象"><a href="#1-3-单例内置对象" class="headerlink" title="1.3 单例内置对象"></a>1.3 单例内置对象</h3><p>对内置对象的定义是：任何由 es 实现提供、与宿主环境无关，并在 es 程序开始执行时就存在的对象</p>
<p>包括 Object、Array 和 String，本节介绍另外两个单列内置对象：Global 和 Math</p>
<p>Global</p>
<p>Global 对象时 es 中最特别的对象，因为代码不会显式的访问它。规定的 Global 对象为一种兜底对象，它所针对的是不属于任何对象的属性和方法。事实上，不存在全局变量或全局函数这种东西。在全局作用域中定义的变量和函数都会变成 Global 对象的属性。前面的函数 isNaN()、isFinite()、parseInt()和 parseFloat()，实际上都是 Global 对象的方法。除了这些还有另外的一些方法</p>
<ul>
<li>URL 编码方法</li>
</ul>
<p>encodeURI()和 encodeURIComponent()方法用于编码统一资源标识符（URI)，以便传给浏览器。有效的 URI 不能包含某些字符，比如空格。</p>
<p>EncodeURI()方法用于对整个 URI 进行编码。这两个方法的主要区别是,encodeURI()不会编码 URL 组件特殊的字符</p>
<p>相对的是 deocdeURI. 和 decodeURIComponent</p>
<ul>
<li>eval 方法</li>
</ul>
<p>最后一个方法可能是整个 es 语言中最强大的，它就是 eval（），这个方法是一个完整的 es 解释器，它接收一个参数，即一个要执行的 es</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">eval</span>(<span class="string">&#x27;console.log(&#x27;</span>hi<span class="string">&#x27;)&#x27;</span>)</span><br></pre></td></tr></table></figure>

<p>通过 eval()执行的代码属于该调用所在上下文，被执行的代码与该上下文拥有相同的作用域链，这意味着定义在包含上下文变量可以在 eval()调用内部被引用</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> msg = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line"><span class="built_in">eval</span>(<span class="string">&quot;console.log(msg)&quot;</span>);</span><br></pre></td></tr></table></figure>

<ul>
<li>Global 对象属性</li>
</ul>
<p>Global 对象有很多属性，其中一些前面已经提过了，像 undefined、NaN 和 Infinity 等特殊值都是 Global 对象的属性。此外，所有原生引用类型构造函数，比图 Object 和 Function 也都是 Global 对象的属性。</p>
<ul>
<li>window 对象</li>
</ul>
<p>虽然没有规定直接访问 Global 对象的方式，但浏览器将 window 对象实现为 Global 对象的代理。因此，所有全局作用域中声明的变量和函数都变成了 window 属性</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> color = <span class="string">&quot;red&quot;</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sayColor</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">window</span>.color);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">window</span>.sayColor();</span><br><span class="line"><span class="comment">// 这里定义了一个名为color的全局变量和一个名为sayColor的全局函数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 另一种获取Global对象的方式使用如下</span></span><br><span class="line"><span class="keyword">let</span> <span class="built_in">global</span> = (<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">this</span>;</span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure>

<ul>
<li>Math</li>
</ul>
<p>es 提供了 Math 对象作为保存数学公式、信息和计算的地方。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.min();</span><br><span class="line"><span class="built_in">Math</span>.max();</span><br><span class="line"><span class="built_in">Math</span>.ceil(); <span class="comment">// 始终向上舍入为最接近的整数</span></span><br><span class="line"><span class="built_in">Math</span>.floor(); <span class="comment">// 方法始终向下舍入为最近的整数</span></span><br><span class="line"><span class="built_in">Math</span>.round(); <span class="comment">// 方法执行四舍五入</span></span><br><span class="line"><span class="built_in">Math</span>.fround(); <span class="comment">// 返回数值最接近的单精度</span></span><br></pre></td></tr></table></figure>

<ul>
<li>random 方法</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.random()方法返回一个<span class="number">0</span>-<span class="number">1</span>范围内的随机数，其中包<span class="number">0</span>不包<span class="number">1</span></span><br></pre></td></tr></table></figure>

<h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><p>js 中的对象称为引用值，几种内置的引用类型可用于创建特定类型的对象</p>
<ul>
<li>引用值与传统面向对象编程语言的类相似，但实现不同</li>
<li>Date 类型提供关于日期和时间的计算</li>
<li>RegExp 类型是 es 支持正则表达式的接口</li>
</ul>
<p>js 比较独特的一点就是，函数实际上是 Function 类型的实例，，也就是说函数是对象，因为是对象，所以函数有方法，可以增强能力</p>
<p>由于原始值包装类型存在，js 中的原始值可以被当成对象来使用。有 3 种原始包装类型：Boolean、Number 和 String</p>
<ul>
<li>每种包装类型都映射到同名的原始类型</li>
<li>以读模式访问原始值时，后台会实例化一个原始值包装类型的对象，借助这个可以对象可以操作相应的数据</li>
<li>涉及原始值的语句执行完毕后，包装对象就会被销毁</li>
</ul>

      
    </div>

    
    
    
      <div>
          
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://skycoin.gitee.io/codeblog/2021/02/27/%E9%9B%86%E5%90%88%E5%BC%95%E7%94%A8%E7%B1%BB/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4083356047,3551369852&fm=26&gp=0.jpg">
      <meta itemprop="name" content="若说">
      <meta itemprop="description" content="立志完成前端知识体系的架构">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="若水的前端博客">
    </span>
      <header class="post-header">
      
        <i class="fa fa-thumb-tack"></i>
        <font color=7D26CD>置顶</font>
      
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/codeblog/2021/02/27/%E9%9B%86%E5%90%88%E5%BC%95%E7%94%A8%E7%B1%BB/" class="post-title-link" itemprop="url">Javascript基础（五）：javascript集合引用类型</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-27 10:14:52" itemprop="dateCreated datePublished" datetime="2021-02-27T10:14:52+08:00">2021-02-27</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-15 09:27:03" itemprop="dateModified" datetime="2021-04-15T09:27:03+08:00">2021-04-15</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/codeblog/categories/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/" itemprop="url" rel="index"><span itemprop="name">前端框架</span></a>
                </span>
            </span>

          
            <span id="/codeblog/2021/02/27/%E9%9B%86%E5%90%88%E5%BC%95%E7%94%A8%E7%B1%BB/" class="post-meta-item leancloud_visitors" data-flag-title="Javascript基础（五）：javascript集合引用类型" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  <span class="post-meta-item">
    
      <span class="post-meta-item-icon">
        <i class="far fa-comment"></i>
      </span>
      <span class="post-meta-item-text">Valine：</span>
    
    <a title="valine" href="/codeblog/2021/02/27/%E9%9B%86%E5%90%88%E5%BC%95%E7%94%A8%E7%B1%BB/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/codeblog/2021/02/27/%E9%9B%86%E5%90%88%E5%BC%95%E7%94%A8%E7%B1%BB/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>[toc]</p>
<h2 id="1-对象"><a href="#1-对象" class="headerlink" title="1.对象"></a>1.对象</h2><h3 id="1-1-Object"><a href="#1-1-Object" class="headerlink" title="1.1 Object"></a>1.1 Object</h3><p>object 是 es 中最常用的类型之一</p>
<p>创建方式</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> person = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">person.name = <span class="string">&quot;jake&quot;</span>;</span><br><span class="line">person.age = <span class="number">29</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> person = &#123;</span><br><span class="line">  name: <span class="string">&quot;jake&quot;</span>,</span><br><span class="line">  age: <span class="number">29</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>虽然属性一般是通过点语法来存取的，也可以使用括号</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">person[<span class="string">&#x27;name&#x27;</span>]</span><br><span class="line">person.name</span><br><span class="line"></span><br><span class="line">per = &#123;&#125;</span><br><span class="line">&#123;&#125;</span><br><span class="line">per[<span class="string">&#x27;first name&#x27;</span>] = <span class="string">&#x27;bob&#x27;</span></span><br><span class="line"><span class="string">&quot;bob&quot;</span></span><br><span class="line">per</span><br><span class="line">&#123;first name: <span class="string">&quot;bob&quot;</span>&#125;</span><br><span class="line">per[<span class="string">&#x27;first name&#x27;</span>]</span><br><span class="line"><span class="string">&quot;bob&quot;</span></span><br></pre></td></tr></table></figure>

<h3 id="1-2-Array"><a href="#1-2-Array" class="headerlink" title="1.2 Array"></a>1.2 Array</h3><p>es 数组也是一组有序的数据，但跟其他语言不同的是，数组中每个槽位可以存储任意类型的数据。这意味着可以创建一个数组，他的第一个元素是字符串，第二个元素是数值，第三个是对象，es 数组也是动态大小的，会随着数据添加而自动增长</p>
<h4 id="1-2-1-创建数组"><a href="#1-2-1-创建数组" class="headerlink" title="1.2.1 创建数组"></a>1.2.1 创建数组</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br></pre></td></tr></table></figure>

<p>如果知道数组中元素的数量，那么可以给构造函数传入一个值，然后 length 属性就会被自动创建并设置为这个值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = <span class="keyword">new</span> <span class="built_in">Array</span>(<span class="number">20</span>);</span><br><span class="line"><span class="keyword">let</span> colors = <span class="keyword">new</span> <span class="built_in">Array</span>(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>在使用 Array 构造函数的时候，也可以省略 new 操作符。结果是一样的</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = <span class="built_in">Array</span>(<span class="number">3</span>);</span><br><span class="line"><span class="keyword">let</span> names = <span class="built_in">Array</span>(<span class="string">&quot;bob&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>另一种创建数组的方法是字面量表示法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>];</span><br><span class="line"><span class="comment">// 与对象一样，在使用数组字面量表示法创建数组不会调用Array构造函数</span></span><br></pre></td></tr></table></figure>

<p>Array 构造函数还有两个 es6 新增的数组静态方法：from 和 of。from()用于将类数组结构转换为数组实例，而 of（）用于将一组参数转换为数组实例</p>
<p>Array.from()的第一个参数是一个类数组对象，即任何可迭代的结构，或者有一个 length 属性和可索引元素的结构。这种方式可用于很多场合</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>().set(<span class="number">1</span>, <span class="number">2</span>);</span><br><span class="line"><span class="built_in">Array</span>.from(m); <span class="comment">// [[1,2]]</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getArray</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">Array</span>.from(<span class="built_in">arguments</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">Array</span>.from(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>);</span><br></pre></td></tr></table></figure>

<p>Array.from()还接收第二个可选的映射函数。这个函数可以直接增强新数组的值，而不许像调用 Array.from().map()那样先创建一个中间数组，还可以接收第三个参数，用于指定映射函数中的 this 值。但这个重写的 this 在箭头函数中不适用</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const a1 &#x3D; [1,2,3,4]</span><br><span class="line">const a2 &#x3D; Array.from(a1,x &#x3D;&gt; x**2)</span><br><span class="line">const a3 &#x3D; Array.from(a1,function(x)&#123;</span><br><span class="line">	return x ** this.expoenent</span><br><span class="line">&#125;,&#123;expoenent:2&#125;)</span><br></pre></td></tr></table></figure>

<p>Array.of()可以把一组参数转换为数组。这个方法用于替代在 es6 之前常用的 Array.prototype.slice.call(arguments)，一种异常笨拙的将 arguments 对象转换成为数组的写法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Array</span>.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>); <span class="comment">// [1,2,3,4]</span></span><br><span class="line"><span class="built_in">Array</span>.of(<span class="literal">undefined</span>); <span class="comment">// [undefined]</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-2-数组空位"><a href="#1-2-2-数组空位" class="headerlink" title="1.2.2 数组空位"></a>1.2.2 数组空位</h4><p>使用数组字面量初始化数组时，可以使用一串逗号来创建空位(hole)</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> options = [, , , , ,]; <span class="comment">//创建包含5个元素的数组</span></span><br><span class="line"><span class="built_in">console</span>.log(options.length); <span class="comment">// 5</span></span><br></pre></td></tr></table></figure>

<p>es6 新增方法和迭代器与早期 es 版本中存在的方法行为不同。ES6 新增方法普遍将这些空位当成存在的元素，只不过值是 undefined</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> options = [<span class="number">1</span>，，，，<span class="number">5</span>]</span><br><span class="line">options.map(<span class="function">() =&gt;</span> <span class="number">6</span>) <span class="comment">// [6,,,,,6]</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-3-数组索引"><a href="#1-2-3-数组索引" class="headerlink" title="1.2.3 数组索引"></a>1.2.3 数组索引</h4><p>要取得或设置数组的值，需要使用中括号并提供相应值的数字索引</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 数组length属性的独到之处是，他不是只读的。通过修改length属性，可以从数组末尾删除或添加元素</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>];</span><br><span class="line">colors.length = <span class="number">2</span>;</span><br><span class="line">colors[<span class="number">2</span>]; <span class="comment">// undefined</span></span><br><span class="line"><span class="comment">// 可以从数组末尾删除或添加元素</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-4-检测数组"><a href="#1-2-4-检测数组" class="headerlink" title="1.2.4 检测数组"></a>1.2.4 检测数组</h4><p>判断一个对象是不是数组</p>
<p>只有一个网页（因而只有一个全局作用域）的情况下，使用 instanceof 操作</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(value <span class="keyword">instanceof</span> <span class="built_in">Array</span>)&#123;</span><br><span class="line">  <span class="comment">// 操作数组</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="1-2-5-迭代器方法"><a href="#1-2-5-迭代器方法" class="headerlink" title="1.2.5 迭代器方法"></a>1.2.5 迭代器方法</h4><p>在 es6 中，Array 的原型上暴露 3 个用于检索数组内容的方法：keys()、values()和 entries()。keys()返回数组索引的迭代器，values（）返回数组元素的迭代器，而 entries()返回索引/值对的迭代器</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> a = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>];</span><br><span class="line"><span class="keyword">const</span> akeys = <span class="built_in">Array</span>.from(a.keys());</span><br><span class="line"><span class="keyword">const</span> aValues = <span class="built_in">Array</span>.from(a.values());</span><br><span class="line"><span class="keyword">const</span> aEntries = <span class="built_in">Array</span>.from(a.entries);</span><br></pre></td></tr></table></figure>

<p>使用 es6 的解构可以非常容易的循环</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> a = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> [idx, ele] <span class="keyword">of</span> a.entries()) &#123;</span><br><span class="line">  alert(idx);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="1-2-6-复制和填充方法"><a href="#1-2-6-复制和填充方法" class="headerlink" title="1.2.6 复制和填充方法"></a>1.2.6 复制和填充方法</h4><p>es6 新增了两个方法：批量复制方法 copyWithin()，以及填充数组方法 fill()。这两个方法的函数签名类似，都需要指定既有数组实例上的一个范围，包括开始的索引，不包含结束索引，使用方法不会改变数组的大小</p>
<p>使用 fill()的方法可以向一个已有的数组中插入全部或部分相同的值。开始索引用于指定开始填充的位置，它是可选的</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> zeros = [<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>];</span><br><span class="line">zeros.fill(<span class="number">5</span>);</span><br><span class="line">zeros.fill(<span class="number">0</span>);</span><br><span class="line">zeros.fill(<span class="number">6</span>, <span class="number">3</span>); <span class="comment">// [0,0,0,6,6]</span></span><br><span class="line">zeros.fill(<span class="number">0</span>); <span class="comment">// 重置</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 填充索引大于等于1 且小于3的元素</span></span><br><span class="line">zeros.fill(<span class="number">7</span>, <span class="number">1</span>, <span class="number">3</span>); <span class="comment">// [0,7,7,0,0]</span></span><br><span class="line"></span><br><span class="line">zeros.fill(<span class="number">8</span>, -<span class="number">4</span>, -<span class="number">1</span>); <span class="comment">// [0,8,8,8,0]</span></span><br></pre></td></tr></table></figure>

<p>Fill()静默忽略超出数组边界、零长度及方向相反的索引范围</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> zeroes = [<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>];</span><br><span class="line">zeros.fill(<span class="number">1</span>, -<span class="number">10</span>, -<span class="number">6</span>); <span class="comment">// [0,0,0,0,0,0]</span></span><br><span class="line"><span class="comment">// 索引过高，忽略</span></span><br><span class="line">zeros.fill(<span class="number">1</span>, <span class="number">10</span>, <span class="number">15</span>); <span class="comment">// 0,0,0,0,0</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 索引过高忽略</span></span><br><span class="line">zeros.fill(<span class="number">4</span>, <span class="number">3</span>, <span class="number">10</span>); <span class="comment">//[0,0,0,0,0]</span></span><br></pre></td></tr></table></figure>

<p>与 fill 不同 copyWithin()会按照指定范围浅复制数组中的部分内容，然后将他们插入到指定索引开始的位置。开始索引和结束索引则 fill()使用</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> ints,</span><br><span class="line">  reset = <span class="function">() =&gt;</span> (ints = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>]);</span><br><span class="line">reset();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 复制数组的前面两个元素到后面两个元素</span></span><br><span class="line"><span class="comment">// copyWithin() 方法用于从数组的指定位置拷贝元素到数组的另一个指定位置中。</span></span><br><span class="line"><span class="keyword">var</span> fruits = [<span class="string">&quot;Banana&quot;</span>, <span class="string">&quot;Orange&quot;</span>, <span class="string">&quot;Apple&quot;</span>, <span class="string">&quot;Mango&quot;</span>];</span><br><span class="line">fruits.copyWithin(<span class="number">2</span>, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// copyWithin()j静默忽略超出数组边界、零长度及方向相反的索引范围</span></span><br><span class="line"><span class="keyword">let</span> ints;</span><br><span class="line">reset = <span class="function">() =&gt;</span> (ints = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>]);</span><br><span class="line">reset();</span><br><span class="line"><span class="comment">// 索引过低忽略</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-7-转换方法"><a href="#1-2-7-转换方法" class="headerlink" title="1.2.7 转换方法"></a>1.2.7 转换方法</h4><p>所有对象都有 toLocaleString()、toString()和 valueOf（）方法。其中 valueOf（）返回的还是数组本身。而 toString()返回由数组中每个值的等效字符串拼接而成的一个一个逗号分隔的字符串。也就是说每个值都会调用 toString 方法，以得到最终的字符串</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>];</span><br><span class="line">colors</span><br><span class="line">  .toString() <span class="comment">// a,b,c</span></span><br><span class="line"></span><br><span class="line">  [(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>)].valueOf()(<span class="number">3</span>)</span><br><span class="line">  [(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>)][(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>)].toString();</span><br><span class="line"><span class="string">&quot;a,b,c&quot;</span>[(<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>)].toLocaleString();</span><br><span class="line">(<span class="string">&quot;a,b,c&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>Join 方法</p>
<p>如果数组中某一项是 null 或 undefined,则在，则在 join()、toLocaleString()、toString()和 valueOf 返回的结果中会以空字符串表示</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>];</span><br><span class="line">colors.join(<span class="string">&quot;,&quot;</span>);</span><br><span class="line">colors.join(<span class="string">&quot;||&quot;</span>);</span><br></pre></td></tr></table></figure>

<h4 id="1-2-8-栈方法"><a href="#1-2-8-栈方法" class="headerlink" title="1.2.8 栈方法"></a>1.2.8 栈方法</h4><p>es 给数组提供几个方法，让他看起来像是另外一种数据结构。数组对象可以像栈一样，也就是一种限制插入和删除项的数据结构。</p>
<p>Push()方法接受任意数量的参数，并将它们添加到数组末尾，返回数组的最新长度。pop()方法则用于删除数组的最后一项，同时减少数组的 length 值，返回被删除的项</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line"><span class="keyword">let</span> count = colors.push(<span class="string">&quot;red&quot;</span>, <span class="string">&quot;green&quot;</span>);</span><br><span class="line">alert(count);</span><br><span class="line">count = colors.push(<span class="string">&quot;black&quot;</span>);</span><br><span class="line">alert(count);</span><br><span class="line"><span class="keyword">let</span> item = colors.pop();</span><br><span class="line">alert(item);</span><br><span class="line">alert(colors.length);</span><br></pre></td></tr></table></figure>

<h4 id="1-2-9-队列方法"><a href="#1-2-9-队列方法" class="headerlink" title="1.2.9 队列方法"></a>1.2.9 队列方法</h4><p>队列以先进先出形式进行访问。要想要模拟队列就差一个从数组开头取得数据的方法了。这个数组方法叫做 shift(),它会删除数组的第一项并返回它，然后数组长度减 1.使用 shift()和 push()</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line"><span class="keyword">let</span> count = colors.push(<span class="string">&quot;red&quot;</span>, <span class="string">&quot;green&quot;</span>);</span><br><span class="line">count = colors.push(<span class="string">&quot;black&quot;</span>);</span><br><span class="line"><span class="keyword">let</span> item = color.shift(); <span class="comment">// 取得第一项</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// es也为数组提供了unshift()方法。</span></span><br><span class="line"><span class="comment">// 在数组开头添加任意多个值，然后返回新的数组长度。</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-10-排序方法"><a href="#1-2-10-排序方法" class="headerlink" title="1.2.10 排序方法"></a>1.2.10 排序方法</h4><p>两个方法可以用来排序 ： reverse()和 sort()</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> values = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];</span><br><span class="line">values.reverse(); <span class="comment">// [4, 3, 2, 1]</span></span><br></pre></td></tr></table></figure>

<p>默认情况下使用 sort()会按照升序重新排列数组元素。</p>
<p>为此 sort（）会在每一项上调用 String()转型函数，然后比较字符串来决定顺序。即使数组的元素都是数值，也会先把数组转换为字符</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> values = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">10</span>, <span class="number">5</span>];</span><br><span class="line">values.sort(); <span class="comment">// [0, 1, 10, 5]</span></span><br></pre></td></tr></table></figure>

<p>因为字符串“10”在字符串”5”的前头。为此 sort()方法可以接受一个比较函数，用于判断哪个值应该排在前面</p>
<p>比较函数接受的两个参数，如果第一个参数应该排到第二个参数前面，就会返回负值；两个参数相等，返回 0；如果第一个参数应该排在第二个参数后面，就返回正值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">compare</span>(<span class="params">value1, value2</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (value1 &lt; value2) &#123;</span><br><span class="line">    <span class="keyword">return</span> -<span class="number">1</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (value1 &gt; value2) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这个比较函数可以适用于大多数数据类型，可以把它当成参数传给 sort（）方法，如下</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> values = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">3</span>];</span><br><span class="line">values.sort(compare); <span class="comment">// [0,1,2,3,4]</span></span><br></pre></td></tr></table></figure>

<p>如果数组的元素是数值，或者是其 valueOf()方法返回数值的对象</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">compare</span>(<span class="params">value1, value2</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> value2 - value1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> points = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">30</span>, <span class="number">4</span>, <span class="number">3</span>];</span><br><span class="line">points.sort(<span class="function">(<span class="params">a, b</span>) =&gt;</span> a - b); <span class="comment">// (5) [1, 2, 3, 4, 30]</span></span><br></pre></td></tr></table></figure>

<p><strong>补充 sort 原理</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">如果调用该方法时没有使用参数，将按字母顺序对数组中的元素进行排序，说得更精确点，是按照字符编码的顺序进行排序。要实现这一点，首先应把数组的元素都转换成字符串（如有必要），以便进行比较。</span><br><span class="line"></span><br><span class="line">如果想按照其他标准进行排序，就需要提供比较函数，该函数要比较两个值，然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b，其返回值如下：</span><br><span class="line"></span><br><span class="line">若 a 小于 b，在排序后的数组中 a 应该出现在 b 之前，则返回一个小于 <span class="number">0</span> 的值。</span><br><span class="line">若 a 等于 b，则返回 <span class="number">0</span>。</span><br><span class="line">若 a 大于 b，则返回一个大于 <span class="number">0</span> 的值。</span><br></pre></td></tr></table></figure>

<h4 id="1-2-11-操作方法"><a href="#1-2-11-操作方法" class="headerlink" title="1.2.11 操作方法"></a>1.2.11 操作方法</h4><p>对于数组中的元素，我们有很多操作方法。</p>
<ul>
<li>Concat（）方法可以在现有数组的全部元素基础上创建一个新数组。它首先会创建一个当前数组的副本，然后把它的参数添加到副本末尾，最后返回这个新构建的数组。如果传入一个数组，则 concat()会把这些数组的每一项都添加到结果数组。如果参数不是数组，则直接把它们添加到结果数组末尾。</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;red&quot;</span>, <span class="string">&quot;green&quot;</span>, <span class="string">&quot;blue&quot;</span>];</span><br><span class="line"><span class="keyword">let</span> colors2 = colors.concat(<span class="string">&quot;yellow&quot;</span>, [<span class="string">&quot;black&quot;</span>, <span class="string">&quot;brow&quot;</span>]); <span class="comment">// [&#x27;red&#x27;&#x27;&#x27;,&#x27;green&#x27;,&#x27;blue&#x27;,&#x27;yellow&#x27;,&#x27;black&#x27;,&#x27;brow&#x27;]</span></span><br></pre></td></tr></table></figure>

<p>打平数组参数的行为可以重写，方法实在参数数组上指定一个特殊的符号：Symbol.isConcat-Spreadable。这个符号能够阻止 concat()打平参数数组。相反，把这个值设置为 true 可以强制打平类数组对象</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>];</span><br><span class="line"><span class="keyword">let</span> newColors = [<span class="string">&quot;d&quot;</span>, <span class="string">&quot;e&quot;</span>];</span><br><span class="line"><span class="keyword">let</span> more = &#123;</span><br><span class="line">  [<span class="built_in">Symbol</span>.isConcatSpreadable]: <span class="literal">true</span>,</span><br><span class="line">  length: <span class="number">2</span>,</span><br><span class="line">  <span class="number">0</span>: <span class="string">&quot;a&quot;</span>,</span><br><span class="line">  <span class="number">1</span>: <span class="string">&quot;b&quot;</span>,</span><br><span class="line">&#125;;</span><br><span class="line">newColors[<span class="built_in">Symbol</span>.isConcatSpreadable] = <span class="literal">false</span>;</span><br><span class="line"><span class="comment">// 强制不打平数组</span></span><br><span class="line"><span class="keyword">let</span> colors2 = colors.concat(<span class="string">&quot;yellow&quot;</span>, newColors);</span><br></pre></td></tr></table></figure>

<p>方法 slice()用于创建一个包含原有数组中一个或多个元素的新数组。slice()方法可以接受一个或两个参数：返回元素的开始索引和结束索引。如果只有一个参数，则 slice()会返回该索引到数组末尾的所有元素。如果有两个元素，slice()返回从开始索引到结束索引对应的所有元素，其中不包含结束索引对应的元素</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> colors = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>];</span><br><span class="line"><span class="keyword">let</span> a = colors.slice(<span class="number">1</span>); <span class="comment">// b,c,d</span></span><br><span class="line"><span class="keyword">let</span> b = colors.slice(<span class="number">1</span>, <span class="number">4</span>); <span class="comment">// b,c,d</span></span><br></pre></td></tr></table></figure>

<p>如果 slice()的参数有负值，那么就以数值长度加上这个负值的结果确定位置</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>];</span><br><span class="line">a.slice(-<span class="number">1</span>); <span class="comment">// d</span></span><br></pre></td></tr></table></figure>

<p>或许最强大的数组方法就属 splice()了，使用它的方式就可以有很多种。splice（）主要目的是在数组中间插入元素，但是 3 种不同的方式使用这个方法</p>
<ul>
<li>删除，需要给 splice()传两个参数：要删除的第一个元素的位置和删除元素的数量</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">b = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>](<span class="number">4</span>)[(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>)];</span><br><span class="line">b.splice(<span class="number">1</span>, <span class="number">2</span>)(<span class="number">2</span>)[(<span class="number">2</span>, <span class="number">3</span>)];</span><br></pre></td></tr></table></figure>

<ul>
<li>插入。需要给 splice()传 3 个参数：开始位置、0（要删除的元素数量）和要插入的元素</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">b</span><br><span class="line">(<span class="number">2</span>) [<span class="number">1</span>, <span class="number">4</span>]</span><br><span class="line">b.splice(<span class="number">0</span>,<span class="number">0</span>,[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])</span><br><span class="line">[]</span><br><span class="line">b</span><br><span class="line">(<span class="number">3</span>) [<span class="built_in">Array</span>(<span class="number">3</span>), <span class="number">1</span>, <span class="number">4</span>]</span><br><span class="line">b.splice(<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>)</span><br><span class="line">[]</span><br><span class="line">b</span><br><span class="line">(<span class="number">4</span>) [<span class="number">1</span>, <span class="built_in">Array</span>(<span class="number">3</span>), <span class="number">1</span>, <span class="number">4</span>]</span><br></pre></td></tr></table></figure>

<ul>
<li>替换。splice()在删除元素的同时可以在指定位置插入新元素，同样需要传递 3 个参数：开始位置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量一致</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">b(<span class="number">4</span>)[(<span class="number">1</span>, <span class="built_in">Array</span>(<span class="number">3</span>), <span class="number">1</span>, <span class="number">4</span>)];</span><br><span class="line"></span><br><span class="line">b.splice(<span class="number">2</span>, <span class="number">1</span>, <span class="string">&quot;red&quot;</span>, <span class="string">&quot;green&quot;</span>)[<span class="number">1</span>];</span><br><span class="line">b(<span class="number">5</span>)[(<span class="number">1</span>, <span class="built_in">Array</span>(<span class="number">3</span>), <span class="string">&quot;red&quot;</span>, <span class="string">&quot;green&quot;</span>, <span class="number">4</span>)];</span><br></pre></td></tr></table></figure>

<p>Splice()方法始终返回这样一个数组，它包含从数组中被删除的元素（如果没有删除元素，则返回空数组）。</p>
<h4 id="1-2-12-搜索和位置方法"><a href="#1-2-12-搜索和位置方法" class="headerlink" title="1.2.12 搜索和位置方法"></a>1.2.12 搜索和位置方法</h4><p>es 提供两类搜索数组的方法：按照严格相等搜索和按断言函数搜索</p>
<p><strong>1.严格相等</strong></p>
<p>es 提供了三个严格相等的搜索方法：indexOf()、lastIndexOf()和 Includes()。其中，前两个方法在所有版本中都可用，第三个是 es7。这些方法都接收两个参数：要查找的元素和一个可选的起始搜索位置。indexOf()和 includes（）方法从数组前头开始往后搜索，lastIndexOf 是从后往前</p>
<p>indexOf 和 lastIndexOf()都返回要查找的元素在数组中的位置，如果没有找到则返回-1.includes（）返回布尔值，表示是否至少找到一个与指定元素匹配的项。会使用全等进行比较。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> number = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];</span><br><span class="line">number.indexOf(<span class="number">4</span>); <span class="comment">// 5 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。</span></span><br><span class="line"><span class="comment">// 第二个参数代表从哪个元素进行搜索</span></span><br></pre></td></tr></table></figure>

<p><strong>2.断言函数</strong></p>
<p>es 也允许按照定义的断言函数搜索数组，每个索引都会调用这个函数，断言函数的返回值决定了相应索引是否被认为匹配</p>
<p>断言函数接受 3 个参数：元素、索引和数组本身。其中元素是数组当前搜索的元素，索引是当前元素的索引，而数组就是正在搜索的数组。断言函数返回真值，表示是否匹配</p>
<p>find()和 findIndex（）方法使用了断言函数。这两个方法都从数组的最小索引开始。find()返回第一个匹配的元素，findIndex()返回第一个匹配元素的索引。这两个方法也都接收第二个可选的参数，用于指定断言函数内部的 this 值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> people = [</span><br><span class="line">  &#123;</span><br><span class="line">    name: <span class="string">&quot;mat&quot;</span>,</span><br><span class="line">    age: <span class="number">27</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    name: <span class="string">&quot;nicole&quot;</span>,</span><br><span class="line">    age: <span class="number">29</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">];</span><br><span class="line">people.find(<span class="function">(<span class="params">element, idx, array</span>) =&gt;</span> element.age &lt; <span class="number">28</span>);</span><br></pre></td></tr></table></figure>

<p>找到匹配后，这两个方法都不继续搜索</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> evens = [<span class="number">2</span>,<span class="number">4</span>,<span class="number">6</span>]</span><br><span class="line">evens.find(<span class="function">(<span class="params">ele,idx,array</span>) =&gt;</span> &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">[<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>].map(<span class="built_in">parseInt</span>)</span><br></pre></td></tr></table></figure>

<h4 id="1-2-13-迭代方法"><a href="#1-2-13-迭代方法" class="headerlink" title="1.2.13 迭代方法"></a>1.2.13 迭代方法</h4><p>es 为数组定义了 5 个迭代方法。每个方法接收两个参数：以每一项为参数运行的函数，以及可选的作为函数作用域对象（影响函数中 this 的值）。传给每个方法的函数接受 3 个参数：数组元素、元素索引和数组本身。因具体方法而异，这个函数的执行结果可能会也可能不会影响返回值</p>
<ul>
<li>Every：对数组每一项都运行传入的函数，如果对每一项函数都返回 true，则这个方法返回 true</li>
<li>Filter:为数组每一项都运行传入的函数，函数返回 true 的项会组成数组之后返回</li>
<li>forEach：对数组每一项运行传入的函数，没有返回值</li>
<li>Map:对数组每一项都运行传入的函数，返回由每次函数调用的结果构成的数组</li>
<li>Some:对数组每一项都运行传入的函数，如果有一项函数返回 true，则这个方法返回 true</li>
</ul>
<p>这些方法都不改变调用他们的数组</p>
<p>every 和 some 是最相似的，都是从数组中搜索复合某个条件的元素。对于 every 来说，传入的函数必须对每一项都返回 true，它才会返回 true，否则返回 false。对 some 来说，只要有一项让传入的函数返回 true，他就回返回 true</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> number = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>];</span><br><span class="line"><span class="keyword">let</span> everyRes = number.every(<span class="function">(<span class="params">item, index, array</span>) =&gt;</span> item &gt; <span class="number">2</span>);</span><br><span class="line"><span class="keyword">let</span> someRes = number.some(<span class="function">(<span class="params">item, index, array</span>) =&gt;</span> item &gt; <span class="number">2</span>);</span><br></pre></td></tr></table></figure>

<p>filter 是基于给定的函数来决定某一项是否应该包含在它的返回的数组中。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> number = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, , <span class="number">4</span>, <span class="number">5</span>];</span><br><span class="line"><span class="keyword">let</span> filterRes = number.filter(<span class="function">(<span class="params">item, index, array</span>) =&gt;</span> item &gt; <span class="number">2</span>);</span><br></pre></td></tr></table></figure>

<p>map 的方法也会返回一个数组，这个数组的每一项都是对原始数组中同样位置的元素运行传入函数而返回的结果。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> number = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, , <span class="number">5</span>];</span><br><span class="line"><span class="keyword">let</span> mapRes = number.map(<span class="function">(<span class="params">item, index, array</span>) =&gt;</span> item * <span class="number">2</span>);</span><br></pre></td></tr></table></figure>

<p>forEach 方法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> number = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line">number.forEach(<span class="function">(<span class="params">item,index,array</span>) =&gt;</span> &#123;<span class="comment">//执行操作&#125;)</span></span><br></pre></td></tr></table></figure>

<p><strong>补充</strong> map 的知识用法</p>
<ul>
<li>map 仅对已分配值（包括）的数组索引进行 callback 调用。</li>
</ul>
<p>题目：[‘1’,’2’,’3’].map(parseInt)</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">答案：[<span class="number">1</span>,<span class="literal">NaN</span>,<span class="literal">NaN</span>]</span><br><span class="line">语法： array.map(callback(currentValue,index,arr),thisValue)</span><br><span class="line">callback:为arr的每个元素调用的函数。每次执行callback时，返回值都会被添加到newArray中。</span><br></pre></td></tr></table></figure>

<ul>
<li>Map()方法返回一个新数组，数组中的元素为原始数组元素调用函数处理后的值</li>
<li>map()方法按照原始数组顺序依次处理元素</li>
<li>map()不会对空数组进行检测</li>
<li>Map()不会改变原始数组</li>
<li>返回值：返回一个新数组，数组中的元素为原始数组元素调用函数处理后的值</li>
<li>thisValue：可选，对象作为该执行回调时使用，传递给函数，用作 this 的值。如果省略了 thisValu,或者传入 null、undefined,那么回调函数的 this 为全局对象</li>
</ul>
<p>回顾 parseInt 运算符</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">parseInt</span>(string, radix)</span><br><span class="line">string:需要解析的字符串</span><br><span class="line">radix:需要解析数字的基数，该值介于<span class="number">2</span>-<span class="number">36</span>之间</span><br><span class="line">如果省略该参数，或者该参数值为<span class="number">0</span>，则数字将以<span class="number">10</span>为基础进行解析。</span><br><span class="line">如果该参数小于<span class="number">2</span>或者大于<span class="number">36</span>，则<span class="built_in">parseInt</span>()将返回<span class="literal">NaN</span></span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">类型转换之显式转换</span><br><span class="line">了解这两个函数后，我们可以模拟一下运行情况</span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">&#x27;1&#x27;</span>, <span class="number">0</span>) <span class="comment">//radix为0时，且string参数不以&#x27;0x&#x27;和&#x27;0&#x27;开头时，按照10为基数处理，这个时候返回1</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">&#x27;2&#x27;</span>, <span class="number">1</span>) <span class="comment">//基数为1（1进制）表示的数中，最大值小于2，所以无法解析，返回NaN</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">&#x27;3&#x27;</span>, <span class="number">2</span>) <span class="comment">//基数为2（2进制）表示的数中，最大值小于3，所以无法解析，返回NaN</span></span><br></pre></td></tr></table></figure>

<h4 id="1-2-14-归并方法"><a href="#1-2-14-归并方法" class="headerlink" title="1.2.14 归并方法"></a>1.2.14 归并方法</h4><p>es 为数组提供了两个归并方法：reduce 和 reduceRight。这两个方法都会迭代数组的所有项，并在此基础上构建一个最终返回值。</p>
<p>这两个方法都会接收两个参数：对每一项都会运行的归并函数，以及可选的以之为归并起点的初始值。传给的参数：上一个归并值、当前项、当前项的索引和数组本身。这个函数返回的任何值都会作为下一次调用同一个函数。如果没有给这两个方法传入可选的第二个参数，则第一次迭代从数组的第二项开始，因此传给归并函数的第一个参数是数组的第一项，第二个参数是数组的第二项</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&gt; <span class="keyword">let</span> v = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]</span><br><span class="line">&gt; <span class="literal">undefined</span></span><br><span class="line">&gt; v.reduce(<span class="function">(<span class="params">prev,cur,index,array</span>) =&gt;</span> prev + cur)</span><br><span class="line">&gt; <span class="number">10</span></span><br><span class="line"></span><br><span class="line">&gt; <span class="keyword">let</span> m = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">4</span>]</span><br><span class="line">&gt; <span class="literal">undefined</span></span><br><span class="line">&gt; m.reduceRight(<span class="function"><span class="keyword">function</span>(<span class="params">prev,cur,index,array</span>)</span>&#123;<span class="keyword">return</span> prev + cur&#125;)</span><br><span class="line">&gt; <span class="number">11</span></span><br></pre></td></tr></table></figure>

<h3 id="1-3-定型数组"><a href="#1-3-定型数组" class="headerlink" title="1.3 定型数组"></a>1.3 定型数组</h3><p>定型数组（typed array)是 es 新增的结构，目的是为了提升向原生库传输数据的效率。js 并没有 typedArray 类型，它所指的其实是一种特殊包含数值类型的数组。</p>
<h4 id="1-3-1-历史"><a href="#1-3-1-历史" class="headerlink" title="1.3.1 历史"></a>1.3.1 历史</h4><p>随着浏览器流行，人们希望它来运行复杂的 3D 应用程序。</p>
<ul>
<li>WebGl</li>
</ul>
<p>是一种 3D 绘图协议，这种绘图技术标准允许把 JavaScript 和 OpenGL ES 2.0 结合在一起，通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定，WebGL 可以为 HTML5 Canvas 提供硬件 3D 加速渲染，这样 Web 开发人员就可以借助系统显卡来在浏览器里更流畅地展示 3D 场景和模型了，还能创建复杂的导航和<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E8%A7%86%E8%A7%89%E5%8C%96/9900523">数据视觉化</a>。显然，WebGL 技术标准免去了开发网页专用渲染插件的麻烦，可被用于创建具有复杂 3D 结构的网站页面，甚至可以用来设计 3D 网页游戏等等</p>
<ul>
<li>定型数组</li>
</ul>
<p>这是一个提供 js 接口的、c 语言风格的浮点数组。js 运行时使用这个类型可以分配、读取和写入数组。这个数组可以直接传给底层图形驱动程序 API，也可以直接从底层获取到</p>
<h4 id="1-3-2-ArrayBuffer"><a href="#1-3-2-ArrayBuffer" class="headerlink" title="1.3.2 ArrayBuffer"></a>1.3.2 ArrayBuffer</h4><p>Float32Array 实际上是一种视图，可以允许 js 运行时访问一块名为 ArrayBuffer 的预分配内存。ArrayBuffer 是所有定型数组及视图引用的基本单位</p>
<p>ArrayBuffer 是一个普通的构造函数，可用于在内存中分配特定数量的字节空间</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> buf = <span class="keyword">new</span> <span class="built_in">ArrayBuffer</span>(<span class="number">16</span>); <span class="comment">// 在内存中分配16字节</span></span><br><span class="line">buf.byteLength;</span><br></pre></td></tr></table></figure>

<p>一经创建就不能在调整大小。不过，可以使用 slice()复制其全部或部分到一个实例中</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> buf1 = <span class="keyword">new</span> <span class="built_in">ArrayBuffer</span>(<span class="number">16</span>)</span><br><span class="line"><span class="keyword">const</span> buf2 = buf1,slice(<span class="number">4</span>,<span class="number">12</span>)</span><br><span class="line">buf2.byteLength. <span class="comment">// 8</span></span><br></pre></td></tr></table></figure>

<p>ArrayBuffer 类似于 c++中的 malloc,但也有几个区别</p>
<ul>
<li>malloc 在分配失败会返回一个 null 指针，ArrayBuffer 在分配失败时会抛出失败</li>
<li>malloc 可以利用虚拟内存，因此最大可分配尺寸可寻址系统内存限制</li>
<li>malloc 调用成功不会初始化实际的地址。声明 ArrayBuffer 则会将所有二进制位初始化为 0</li>
<li>通过 malloc 分配的堆内存除非调用 free 或程序退出，否则系统不能在使用。而通过声明 ArrayBuffer 分配的堆内存可以被当成垃圾回收，不用手动释放</li>
</ul>
<p>应用场景：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">大量的 Web API 用到了<span class="built_in">ArrayBuffer</span>对象和它的视图对象。</span><br><span class="line"></span><br><span class="line">ajax</span><br><span class="line">传统上，服务器通过 AJAX 操作只能返回文本数据，即responseType属性默认为text。XMLHttpRequest第二版XHR2允许服务器返回二进制数据，这时分成两种情况。如果明确知道返回的二进制数据类型，可以把返回类型（responseType）设为arraybuffer；如果不知道，就设为blob。</span><br></pre></td></tr></table></figure>

<h4 id="1-3-3-DateView"><a href="#1-3-3-DateView" class="headerlink" title="1.3.3 DateView"></a>1.3.3 DateView</h4><p>第一种允许你读写 ArrayBuffer 的视图是 DateView.这个视图专为文件 i/o 和网络 i/o 设计</p>
<h4 id="1-3-4-定型数组"><a href="#1-3-4-定型数组" class="headerlink" title="1.3.4 定型数组"></a>1.3.4 定型数组</h4><p>视图：视图是指计算机数据库中的视图，是一个虚拟表，其内容由查询定义。同真实的表一样，视图包含一系列带有名称的列和行数据。</p>
<p>另一种形式的 ArrayBuffer 视图，它特定于一种 elementType 且遵循系统原生的字节序</p>
<p>定型数组行为，从很多数组与普通数组都很相似。定型数组支持如下操作符、方法和属性</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">[];</span><br><span class="line">copyWithin;</span><br><span class="line">entries;</span><br><span class="line">every;</span><br><span class="line">fill;</span><br><span class="line">filter;</span><br><span class="line">find;</span><br><span class="line">findIndex;</span><br><span class="line">forEach;</span><br><span class="line">indexOf;</span><br><span class="line">join;</span><br><span class="line">keys;</span><br><span class="line">lastIndexOf;</span><br><span class="line">length;</span><br><span class="line">map;</span><br><span class="line">reduce;</span><br><span class="line">reduceRight;</span><br><span class="line">reverse;</span><br><span class="line">slice;</span><br><span class="line">some;</span><br><span class="line">sort;</span><br><span class="line">toLocaleString;</span><br><span class="line">toString;</span><br><span class="line">values;</span><br></pre></td></tr></table></figure>

<p>其中返回新数组方法也会返回包含相同元素类型的新定型数组</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> ints = <span class="keyword">new</span> <span class="built_in">Int16Array</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>]);</span><br><span class="line"><span class="keyword">const</span> doubles = ints.map(<span class="function">(<span class="params">x</span>) =&gt;</span> <span class="number">2</span> * x);</span><br><span class="line">doubles <span class="keyword">instanceof</span> <span class="built_in">Int16Array</span>; <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>定型数组有一个 Symbol.iterator 符号属性，因此可以通过 for…of 循环和扩展运算符来操作</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> ints = <span class="keyword">new</span> <span class="built_in">Int16Array</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> int <span class="keyword">of</span> ints) &#123;</span><br><span class="line">  alert(int);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>合并、复制和修改定型数组</li>
</ul>
<p>定型数组同样适用数组缓冲来存储数据，而数组缓冲无法调整大小。因此，下列方法不适用定型数组</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">concat();</span><br><span class="line">pop();</span><br><span class="line">push();</span><br><span class="line">shift();</span><br><span class="line">splice();</span><br><span class="line">unshift();</span><br></pre></td></tr></table></figure>

<p>不过，定型数组也提供了两个新方法，可以快速向外或向内复制数据：set()和 subarray()</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">subarray() 返回一个新的、基于相同 <span class="built_in">ArrayBuffer</span>、元素类型也相同的的 _TypedArray_。开始的索引将会被包括，而结束的索引将不会被包括。TypedArray 是指 typed array types 的其中之一。</span><br></pre></td></tr></table></figure>

<h3 id="1-4-Map"><a href="#1-4-Map" class="headerlink" title="1.4 Map"></a>1.4 Map</h3><p>es6 以前，在 js 中实现键值存储可以使用 Object 来方便高效地完成，也就是使用对象属性作为键，在使用属性来引用值。</p>
<p>Map 是一种新的集合类型，为这门语言带来真正的键/值存储机制。Map 的大多数特性都可以通过 Object 类型实现。</p>
<h4 id="1-4-1-基本-API"><a href="#1-4-1-基本-API" class="headerlink" title="1.4.1 基本 API"></a>1.4.1 基本 API</h4><p>使用 new 关键字和 Map 构造函数可以创建一个空映射</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br></pre></td></tr></table></figure>

<p>如果想在创建的同时初始化实例，可以给 Map 传递一个可迭代的对象，需要包含键/值对数组。可迭代对象中的每个键/值对都会按照迭代顺序插入到新映射实例中</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m1 = <span class="keyword">new</span> <span class="built_in">Map</span>([</span><br><span class="line">  [<span class="string">&quot;key1&quot;</span>, <span class="string">&quot;value1&quot;</span>],</span><br><span class="line">  [<span class="string">&quot;key2&quot;</span>, <span class="string">&quot;value2&quot;</span>],</span><br><span class="line">]);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> m2 = <span class="keyword">new</span> <span class="built_in">Map</span>(&#123;</span><br><span class="line">  [<span class="built_in">Symbol</span>.iterator]: <span class="function"><span class="keyword">function</span>* (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">yield</span> [<span class="string">&quot;key&quot;</span>, <span class="string">&quot;val&quot;</span>];</span><br><span class="line">    <span class="keyword">yield</span> [<span class="string">&quot;key2&quot;</span>, <span class="string">&quot;val2&quot;</span>];</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">m2.size; <span class="comment">// 3</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> m3 = <span class="keyword">new</span> <span class="built_in">Map</span>([[]]);</span><br><span class="line">m3.has(<span class="literal">undefined</span>); <span class="comment">// true</span></span><br><span class="line">m3.get(<span class="literal">undefined</span>); <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure>

<p>初始化之后可以使用 set()方法在添加键值对。可以使用 get()和 has()进行查询，可以通过 size 类型属性获取映射中的键/值对的数量，还可以使用 delete()和 clear()删除值</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line">m.set(<span class="string">&quot;firstname&quot;</span>, <span class="string">&quot;mat&quot;</span>);</span><br><span class="line">m.has(<span class="string">&quot;firstname&quot;</span>); <span class="comment">// true</span></span><br><span class="line">m.get(<span class="string">&quot;firstname&quot;</span>); <span class="comment">// mat</span></span><br></pre></td></tr></table></figure>

<p>Set()方法返回映射实例，因此可以把多个操作连缀起来，包括初始声明</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>().set(<span class="string">&quot;key&quot;</span>, <span class="string">&quot;val&quot;</span>);</span><br><span class="line">m.set(<span class="string">&quot;key1&quot;</span>, <span class="string">&quot;val2&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>与 Object 只能使用数组、字符串或符号作为键不同，Map 可以使用任何 js 数据类型作为键</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line"><span class="keyword">const</span> functionKey = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line"><span class="keyword">const</span> symbolKey = <span class="built_in">Symbol</span>();</span><br><span class="line"><span class="keyword">const</span> objectKey = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">m.set(functionKey, <span class="string">&quot;functionKey&quot;</span>);</span><br><span class="line">m.set(symbolKey, <span class="string">&quot;symbolKey&quot;</span>);</span><br><span class="line">m.get(functionKey);</span><br></pre></td></tr></table></figure>

<p>与严格相等一样，在映射中用作键和值对象及其他“集合”类型，在自己的内容或属性被修改时仍然保持不变</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line"><span class="keyword">const</span> objKey = &#123;&#125;,</span><br><span class="line">  objVal = &#123;&#125;,</span><br><span class="line">  arrKey = [],</span><br><span class="line">  arrVal = [];</span><br><span class="line">m.set(objKey, objVal);</span><br><span class="line">m.set(arrKey, arrVal);</span><br><span class="line">objKey.foo = <span class="string">&quot;foo&quot;</span>;</span><br><span class="line">objVal.bar = <span class="string">&quot;bar&quot;</span>;</span><br><span class="line">arrKey.push(<span class="string">&quot;foo&quot;</span>);</span><br><span class="line">arrValue.push(<span class="string">&quot;bar&quot;</span>);</span><br><span class="line">m.get(objKey); <span class="comment">// &#123;bar:&#x27;bar&#x27;&#125;</span></span><br><span class="line">m.get(arrKey); <span class="comment">// [&#x27;bar&#x27;]</span></span><br></pre></td></tr></table></figure>

<h4 id="1-4-2-顺序与迭代"><a href="#1-4-2-顺序与迭代" class="headerlink" title="1.4.2 顺序与迭代"></a>1.4.2 顺序与迭代</h4><p>与 Object 类型的一个主要差异是，Map 实例会维护键值对的插入顺序，因此可以根据插入顺序执行迭代操作</p>
<p>映射实例可以提供一个迭代器（iterator)，能以插入顺序生成[key,value]形式的数组。通过 entries 的方法或者 Symbol.iterator 属性，它引用 entries()取得这个迭代器：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>().set(<span class="string">&quot;key&quot;</span>, <span class="string">&quot;val&quot;</span>);</span><br><span class="line">m.set(<span class="string">&quot;key1&quot;</span>, <span class="string">&quot;val2&quot;</span>);</span><br><span class="line">m.entries == m[<span class="built_in">Symbol</span>.iterator]; <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>因为 entries 是默认迭代器，所以可以直接对映射实例使用扩展操作，把映射转换为数组</p>
<h4 id="1-4-3-选择-Object-还是-Map"><a href="#1-4-3-选择-Object-还是-Map" class="headerlink" title="1.4.3 选择 Object 还是 Map"></a>1.4.3 选择 Object 还是 Map</h4><p>对象和映射之间存在显著的差别</p>
<ul>
<li>内存占用</li>
</ul>
<p>Object 和 Map 工程级实现在不同浏览器间存在明显差异，但存储单个键/值对所占用的内存数量都会随键的数量线性增加。批量添加或删除键/值则取决于各浏览器对该类型内存分配的工程实现，不同浏览器的情况不同，但给定固定大小的内存，Map 大约可以比 Object 多存储 50%的键/值对</p>
<ul>
<li>插入性能</li>
</ul>
<p>如果代码设计大量插入操作，Map 性能更佳</p>
<ul>
<li>查找速度</li>
</ul>
<p>如果代码设计大量的查找操作，选择 Object 更好一些</p>
<ul>
<li>删除性能</li>
</ul>
<p>使用 delete 删除 object 属性一直以来饱受诟病。目前浏览器出现一些伪删除对象属性的操作，包括把属性值设置为 undefined 或 null。而对大量的引擎来说，Map 的 delete 操作都比插入和查找更快。如果代码涉及到大量删除操作，应该选择 Map</p>
<h3 id="1-5-WeekMap"><a href="#1-5-WeekMap" class="headerlink" title="1.5 WeekMap"></a>1.5 WeekMap</h3><p>es6 新增的弱映射是一种新的集合类型，为了这门语言带来增强的键/值对存储机制。WeekMap 中的 week,描述的就是 js 垃圾回收程序对待弱映射中键的方式</p>
<h4 id="1-5-1-基本-API"><a href="#1-5-1-基本-API" class="headerlink" title="1.5.1 基本 API"></a>1.5.1 基本 API</h4><p>可以通过 new 关键字实例化一个 weekmap</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> wm = <span class="keyword">new</span> <span class="built_in">WeakMap</span>();</span><br></pre></td></tr></table></figure>

<ul>
<li>弱映射中的键只能是 Object 或者继承自 Object 的类型，尝试使用非对象设置键会抛出 TypeError</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> map = <span class="keyword">new</span> <span class="built_in">WeakMap</span>();</span><br><span class="line">map.set(<span class="number">1</span>, <span class="number">2</span>); <span class="comment">// TypeError: Invalid value used as weak map key</span></span><br><span class="line">map.set(<span class="literal">null</span>, <span class="number">2</span>); <span class="comment">// TypeError: Invalid value used as weak map key</span></span><br></pre></td></tr></table></figure>

<ul>
<li>WeakMap 的键名所引用的对象是弱引用</li>
</ul>
<p>WeakMaps 保持了对建名所引用的对象的弱引用</p>
<p>弱引用</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">在计算机程序设计中，弱引用和强引用相对，是指不能确保其引用的对象不会被垃圾回收器回收的引用。一个对象若只被弱引用所引用，则被认为是不可访问的，并因此可能在任何时候回收</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <div>
          
    </div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="若说"
      src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=4083356047,3551369852&fm=26&gp=0.jpg">
  <p class="site-author-name" itemprop="name">若说</p>
  <div class="site-description" itemprop="description">立志完成前端知识体系的架构</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/codeblog/archives/">
        
          <span class="site-state-item-count">5</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/codeblog/categories/">
          
        <span class="site-state-item-count">1</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">1</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/lovebxy" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;lovebxy" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="/codeblog/1490365616@qq.com" title="E-Mail → 1490365616@qq.com"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://weibo.com/yourname" title="Weibo → https:&#x2F;&#x2F;weibo.com&#x2F;yourname" rel="noopener" target="_blank"><i class="fab fa-weibo fa-fw"></i>Weibo</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://plus.google.com/yourname" title="Google → https:&#x2F;&#x2F;plus.google.com&#x2F;yourname" rel="noopener" target="_blank"><i class="fab fa-google fa-fw"></i>Google</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="http://yoursite.com/" title="http:&#x2F;&#x2F;yoursite.com" rel="noopener" target="_blank">test</a>
        </li>
    </ul>
  </div>

      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">若说</span>
</div>

<div class="theme-info">
  <div class="powered-by"></div>
  <span class="post-count">博客全站共25.5k字</span>
</div>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<div class="powered-by">
  <i class="fa fa-user-md"></i>
  <span id="busuanzi_container_site_pv">
    本站访问量:<span id="busuanzi_value_site_pv"></span>次
  </span>
  <span class="post-meta-divider">|</span>
  <span id="busuanzi_container_site_uv">
    本站总访客量：<span id="busuanzi_value_site_uv"></span>人
  </span>
</div>

        








      </div>
    </footer>
  </div>

  
  <script src="/codeblog/lib/anime.min.js"></script>
  <script src="/codeblog/lib/velocity/velocity.min.js"></script>
  <script src="/codeblog/lib/velocity/velocity.ui.min.js"></script>

<script src="/codeblog/js/utils.js"></script>

<script src="/codeblog/js/motion.js"></script>


<script src="/codeblog/js/schemes/pisces.js"></script>


<script src="/codeblog/js/next-boot.js"></script>




  




  
<script src="/codeblog/js/local-search.js"></script>













  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//unpkg.com/valine/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : true,
      notify     : false,
      appId      : 'DbTfuJfplEWGguVvLyabTu99-gzGzoHsz',
      appKey     : 'hkLIIwmXwOd95taiLRxnUrjO',
      placeholder: "Just go go",
      avatar     : 'monsterid',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : true,
      lang       : '' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

  <script type="text/javascript" src="/js/src/clicklove.js"></script>
  <script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>

</body>
</html>
